Fix grab client resume.
authorAndre Noll <maan@systemlinux.org>
Tue, 29 Mar 2011 22:10:29 +0000 (00:10 +0200)
committerAndre Noll <maan@systemlinux.org>
Tue, 29 Mar 2011 22:10:29 +0000 (00:10 +0200)
An active grab client is moved to the inactive list if para_server
stops playing and the grab client is not operating in one-shot mode. In
this state, despite its buffer tree node pointer being NULL, the task
associated with the grab client remains active. This causes para_server
to abort due to the assertion btrn != NULL in btr_node_status().

Fix this bug by always unregistering the task, one-shot mode or not,
and re-registering it later, at the same time the new buffer tree
node for the grab client is allocated.

grab_client.c

index c410b3b..de6df6d 100644 (file)
@@ -131,13 +131,12 @@ static void gc_activate(struct grab_client *gc)
        list_move(&gc->node, &active_grab_client_list);
        gc->btrn = btr_new_node(&(struct btr_node_description)
                EMBRACE(.name = name, .parent = parent));
-       if (!gc->task.pre_select) {
-               gc->task.pre_select = gc_pre_select;
-               gc->task.post_select = gc_post_select;
-               snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name);
-               gc->task.status[sizeof(gc->task.status) - 1] = '\0';
-               register_task(&gc->task);
-       }
+       gc->task.pre_select = gc_pre_select;
+       gc->task.post_select = gc_post_select;
+       snprintf(gc->task.status, sizeof(gc->task.status) - 1, "%s", name);
+       gc->task.status[sizeof(gc->task.status) - 1] = '\0';
+       gc->task.error = 0;
+       register_task(&gc->task);
 }
 
 /**
@@ -156,7 +155,7 @@ void activate_grab_clients(void)
        struct grab_client *gc, *tmp;
 
        list_for_each_entry_safe(gc, tmp, &inactive_grab_client_list, node) {
-               if (gc->task.error < 0) {
+               if (gc->fd < 0) {
                        list_del(&gc->node);
                        free(gc);
                        continue;
@@ -179,11 +178,11 @@ static int gc_close(struct grab_client *gc, int err)
                 * post_select().
                 */
                close(gc->fd);
+               gc->fd = -1;
                free(gc->parent);
                free(gc->name);
                return 1;
        }
-       gc_activate(gc);
        return 0;
 }
 
@@ -210,7 +209,8 @@ static void gc_post_select(__a_unused struct sched *s, struct task *t)
                btr_consume(btrn, ret);
        return;
 err:
-       t->error = gc_close(gc, ret)? ret : 0;
+       gc_close(gc, ret);
+       t->error = ret;
 }
 
 static int gc_check_args(int argc, char **argv, struct grab_client *gc)