vss: Avoid use after free in vss_send().
[paraslash.git] / osx_write.c
index 2894f11eb6672dd5f06fa1f3166f6a77afad7ae0..18a2c084b9dfce04a309ecf4286b01ddc81ad898 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2006-2012 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 2006 Andre Noll <maan@tuebingen.mpg.de>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -274,9 +274,9 @@ static inline bool need_drain_delay(struct private_osx_write_data *powd)
        return btr_get_input_queue_size(powd->callback_btrn) != 0;
 }
 
-static void osx_write_pre_select(struct sched *s, struct task *t)
+static void osx_write_pre_select(struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_osx_write_data *powd = wn->private_data;
        int ret;
        bool drain_delay_nec = false;
@@ -301,29 +301,32 @@ static void osx_write_pre_select(struct sched *s, struct task *t)
        sched_request_timeout_ms(50, s);
 }
 
-static void osx_write_post_select(__a_unused struct sched *s, struct task *t)
+static int osx_write_post_select(__a_unused struct sched *s, void *context)
 {
-       struct writer_node *wn = container_of(t, struct writer_node, task);
+       struct writer_node *wn = context;
        struct private_osx_write_data *powd = wn->private_data;
        struct btr_node *btrn = wn->btrn;
        int ret;
 
+       ret = task_get_notification(wn->task);
+       if (ret < 0)
+               goto fail;
        if (!powd) {
                ret = btr_node_status(btrn, wn->min_iqs, BTR_NT_LEAF);
                if (ret == 0)
-                       return;
+                       return 0;
                if (ret < 0)
-                       goto remove_btrn;
+                       goto fail;
                ret = core_audio_init(wn);
                if (ret < 0)
-                       goto remove_btrn;
+                       goto fail;
                powd = wn->private_data;
                ret = -E_UNIT_START;
                if (AudioOutputUnitStart(powd->audio_unit) != noErr) {
                        AudioUnitUninitialize(powd->audio_unit);
                        CloseComponent(powd->audio_unit);
                        btr_remove_node(&powd->callback_btrn);
-                       goto remove_btrn;
+                       goto fail;
                }
        }
        mutex_lock(powd->mutex);
@@ -332,19 +335,20 @@ static void osx_write_post_select(__a_unused struct sched *s, struct task *t)
                btr_pushdown(btrn);
        if (ret < 0 && need_drain_delay(powd))
                ret = 0;
-       if (ret >= 0) {
-               mutex_unlock(powd->mutex);
-               return;
-       }
-       AudioOutputUnitStop(powd->audio_unit);
-       AudioUnitUninitialize(powd->audio_unit);
-       CloseComponent(powd->audio_unit);
-       btr_remove_node(&powd->callback_btrn);
        mutex_unlock(powd->mutex);
-remove_btrn:
+       if (ret >= 0)
+               return 0;
+fail:
+       assert(ret < 0);
+       if (powd && powd->callback_btrn) {
+               AudioOutputUnitStop(powd->audio_unit);
+               AudioUnitUninitialize(powd->audio_unit);
+               CloseComponent(powd->audio_unit);
+               btr_remove_node(&powd->callback_btrn);
+       }
        btr_remove_node(&wn->btrn);
        PARA_NOTICE_LOG("%s\n", para_strerror(-ret));
-       t->error = ret;
+       return ret;
 }
 
 /**
@@ -362,9 +366,6 @@ void osx_write_init(struct writer *w)
        w->post_select = osx_write_post_select;
        w->parse_config_or_die = osx_write_parse_config_or_die;
        w->free_config = osx_free_config;
-       w->help = (struct ggo_help) {
-               .short_help = osx_write_args_info_help,
-               .detailed_help = osx_write_args_info_detailed_help
-       };
+       w->help = (struct ggo_help)DEFINE_GGO_HELP(osx_write);
        osx_write_cmdline_parser_free(&dummy);
 }