From 450dc78c2298f8ebc8ec494288c6b04aa2359e2d Mon Sep 17 00:00:00 2001 From: Andre Date: Sun, 4 Jun 2006 22:59:38 +0200 Subject: [PATCH] More audiod fixes The bug-quality rises. This patch fixes the select timeout after receiver open. As the pre_select function of the receiver just opened will be called _after_ the upcoming select call, we might block for the time of that call. Only afterwards, the receiver can change the timeout. Fix this problem by changing the timeout to a minimum from within start_receiver() (which gets called by audiod_pre_select()). Resume on server restart. This was broken by design as it used sleep() and also caused problems with the alsa writer being restarted too early. We can do much better with the new scheduler, so introduce a new field "restart_barrier" in struct status_task and restart para_client and the receivers not before this time. Also, set the default timeout to a ridiculous value to detect further timeout problems and do not kill the decoders even if the status pipe went south. --- audiod.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/audiod.c b/audiod.c index 29ceda53..f653c4f7 100644 --- a/audiod.c +++ b/audiod.c @@ -137,6 +137,8 @@ struct status_task { unsigned loaded; /** the associated task structure */ struct task task; + /** do not restart client command until this time */ + struct timeval restart_barrier; }; static struct status_task status_task_struct, *stat_task = &status_task_struct; @@ -584,7 +586,7 @@ static void close_stat_pipe(void) close(stat_task->fd); del_close_on_fork_list(stat_task->fd); stat_task->fd = -1; - kill_all_decoders(); +// kill_all_decoders(); for (i = 0; i < NUM_STAT_ITEMS; i++) { free(stat_item_values[i]); stat_item_values[i] = NULL; @@ -798,7 +800,7 @@ static int is_frozen(int format) return (tv_diff(now, &a->restart_barrier, NULL) > 0)? 0 : 1; } -static void open_current_receiver(void) +static void open_current_receiver(struct sched *s) { int i; @@ -810,6 +812,13 @@ static void open_current_receiver(void) if (decoder_running(i) || is_frozen(i)) return; open_receiver(i); + /* + * the receiver didn't get a chance to put his fd to the fd set. + * Make the upcoming select() return immediately to avoid a long + * timeout. + */ + s->timeout.tv_sec = 0; + s->timeout.tv_usec = 1; } static void compute_time_diff(const struct timeval *status_time) @@ -947,7 +956,7 @@ static void audiod_pre_select(struct sched *s, __a_unused struct task *t) if (audiod_status != AUDIOD_ON || !playing) kill_all_decoders(); else if (playing) - open_current_receiver(); + open_current_receiver(s); FOR_EACH_SLOT(i) { struct slot_info *s = &slot[i]; struct audio_format_info *a; @@ -1612,12 +1621,16 @@ static void init_command_task(struct command_task *ct) static void status_event_handler(__a_unused struct task *t) { + struct timeval delay = {1, 0}; + int i; + struct status_task *st = t->private_data; + PARA_ERROR_LOG("%s\n", PARA_STRERROR(-t->ret)); close_stat_pipe(); /* avoid busy loop if server is down */ - while (sleep(1) > 0) /* FIXME */ - ; /* try again*/ - + tv_add(now, &delay, &st->restart_barrier); + FOR_EACH_AUDIO_FORMAT(i) + afi[i].restart_barrier = st->restart_barrier; } static void status_pre_select(struct sched *s, struct task *t) @@ -1626,7 +1639,8 @@ static void status_pre_select(struct sched *s, struct task *t) t->ret = 1; if (st->fd >= 0 && audiod_status == AUDIOD_OFF) close_stat_pipe(); - if (st->fd < 0 && audiod_status != AUDIOD_OFF) { + if (st->fd < 0 && audiod_status != AUDIOD_OFF + && tv_diff(now, &st->restart_barrier, NULL) > 0) { st->fd = open_stat_pipe(); st->loaded = 0; st->buf[0] = '\0'; @@ -1655,14 +1669,12 @@ static void status_post_select(struct sched *s, struct task *t) static void init_status_task(struct status_task *st) { + memset(st, 0, sizeof(struct status_task)); st->task.pre_select = status_pre_select; st->task.post_select = status_post_select; st->task.event_handler = status_event_handler; st->task.private_data = st; - st->task.flags = 0; - st->loaded = 0; st->fd = -1; - st->buf[0] = '\0'; sprintf(st->task.status, "status task"); } @@ -1732,7 +1744,7 @@ int main(int argc, char *argv[]) register_task(&cmd_task->task); register_task(&stat_task->task); register_task(audiod_task); - s.default_timeout.tv_sec = 0; + s.default_timeout.tv_sec = 3; s.default_timeout.tv_usec = 99 * 1000; ret = sched(&s); -- 2.30.2