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.
unsigned loaded;
/** the associated task structure */
struct task 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;
};
static struct status_task status_task_struct, *stat_task = &status_task_struct;
close(stat_task->fd);
del_close_on_fork_list(stat_task->fd);
stat_task->fd = -1;
close(stat_task->fd);
del_close_on_fork_list(stat_task->fd);
stat_task->fd = -1;
for (i = 0; i < NUM_STAT_ITEMS; i++) {
free(stat_item_values[i]);
stat_item_values[i] = NULL;
for (i = 0; i < NUM_STAT_ITEMS; i++) {
free(stat_item_values[i]);
stat_item_values[i] = NULL;
return (tv_diff(now, &a->restart_barrier, NULL) > 0)? 0 : 1;
}
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)
if (decoder_running(i) || is_frozen(i))
return;
open_receiver(i);
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)
}
static void compute_time_diff(const struct timeval *status_time)
if (audiod_status != AUDIOD_ON || !playing)
kill_all_decoders();
else if (playing)
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;
FOR_EACH_SLOT(i) {
struct slot_info *s = &slot[i];
struct audio_format_info *a;
static void status_event_handler(__a_unused struct task *t)
{
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 */
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)
}
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();
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';
st->fd = open_stat_pipe();
st->loaded = 0;
st->buf[0] = '\0';
static void init_status_task(struct status_task *st)
{
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.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;
sprintf(st->task.status, "status task");
}
sprintf(st->task.status, "status task");
}
register_task(&cmd_task->task);
register_task(&stat_task->task);
register_task(audiod_task);
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);
s.default_timeout.tv_usec = 99 * 1000;
ret = sched(&s);