From d46fe38dcada4108ed49a0e621376df0f7913fe3 Mon Sep 17 00:00:00 2001 From: Andre Date: Thu, 1 Jun 2006 19:54:45 +0200 Subject: [PATCH] sched/audiod feature: task list and kill This allows to control the internal state of the scheduler. --- NEWS | 2 ++ audiod.c | 101 +++++++++++++++++++++++++++++++++++++++++++------------ error.h | 9 ++++- sched.c | 46 ++++++++++++++++++++++++- sched.h | 2 ++ 5 files changed, 137 insertions(+), 23 deletions(-) diff --git a/NEWS b/NEWS index 69d303b3..06330e72 100644 --- a/NEWS +++ b/NEWS @@ -20,6 +20,8 @@ A bunch of new features and core changes. o random/playlist selector: improved info strings + o new audiod commands: tasks, kill + 0.2.12 (2006-05-12) "oriented abstraction" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/audiod.c b/audiod.c index 68c84fb4..f08be183 100644 --- a/audiod.c +++ b/audiod.c @@ -168,10 +168,12 @@ struct audiod_command { static int com_grab(int, char *); static int com_cycle(int, int, char **); static int com_help(int, int, char **); +static int com_kill(int, int, char **); static int com_off(int, int, char **); static int com_on(int, int, char **); static int com_sb(int, int, char **); static int com_stat(int, int, char **); +static int com_tasks(int, int, char **); static int com_term(int, int, char **); static struct audiod_command cmds[] = { { @@ -210,6 +212,16 @@ static struct audiod_command cmds[] = { "\n" " -- Beatles: Help\n" +}, +{ +.name = "kill", +.handler = com_kill, +.description = "kill an active audiod task", +.synopsis = "kill task_id [task_id ...]", +.help = + +"call sched_unregister() and the event_handler of the given task(s)\n" + }, { .name = "off", @@ -252,6 +264,16 @@ static struct audiod_command cmds[] = { "Dump given status items (all if none given) to stdout.\n" +}, +{ +.name = "tasks", +.handler = com_tasks, +.description = "list current tasks", +.synopsis = "tasks", +.help = + +"print the list of task ids together with the status of each task\n" + }, { .name = "term", @@ -605,6 +627,8 @@ int num_filters(int audio_format_num) static void filter_event_handler(struct task *t) { PARA_NOTICE_LOG("%s\n", PARA_STRERROR(-t->ret)); + struct filter_chain *fc = t->private_data; + fc->eof = 1; unregister_task(t); } @@ -677,15 +701,10 @@ static struct filter_node *find_filter_node(int slot_num, int format, int filter static void wng_event_handler(struct task *t) { struct writer_node_group *wng = t->private_data; - int i; + PARA_INFO_LOG("%s\n", PARA_STRERROR(-t->ret)); + wng->eof = 1; wng_unregister(wng); - FOR_EACH_SLOT(i) { - struct slot_info *s = &slot[i]; - if (s->wng != wng) - continue; - PARA_INFO_LOG("slot %d: %s\n", i, PARA_STRERROR(-t->ret)); - } } static void open_writers(int slot_num) @@ -730,9 +749,11 @@ static void open_writers(int slot_num) static void rn_event_handler(struct task *t) { -// struct receiver_node *rn = t->private_data; + struct receiver_node *rn = t->private_data; + PARA_NOTICE_LOG("%s\n", PARA_STRERROR(-t->ret)); unregister_task(t); + rn->eof = 1; } static void open_receiver(int format) @@ -1226,6 +1247,33 @@ out: return ret; } +static int com_tasks(int fd, __a_unused int argc, __a_unused char **argv) +{ + char *tl = get_task_list(); + int ret = 1; + if (tl) + ret = client_write(fd, tl); + free(tl); + if (ret > 0) + close(fd); + return ret; +} + +static int com_kill(int fd, int argc, char **argv) +{ + int i, ret = 1; + if (argc < 2) + return -E_AUDIOD_SYNTAX; + for (i = 1; i < argc; i++) { + ret = kill_task(argv[i]); + if (ret < 0) + break; + } + if (ret > 0) + close(fd); + return ret; +} + static int com_stat(int fd, __a_unused int argc, __a_unused char **argv) { int i, ret; @@ -1492,7 +1540,11 @@ static int open_stat_pipe(void) void signal_event_handler(struct task *t) { struct signal_task *st = t->private_data; - handle_signal(st->signum); + + if (t->ret != -E_SIGNAL_CAUGHT) + PARA_ERROR_LOG("%s (ignored)\n", PARA_STRERROR(-t->ret)); + else + handle_signal(st->signum); } void signal_pre_select(struct sched *s, struct task *t) @@ -1555,6 +1607,16 @@ static void init_command_task(struct command_task *ct) sprintf(ct->task.status, "command task"); } +static void status_event_handler(__a_unused struct task *t) +{ + 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*/ + +} + static void status_pre_select(struct sched *s, struct task *t) { struct status_task *st = t->private_data; @@ -1573,29 +1635,26 @@ static void status_pre_select(struct sched *s, struct task *t) static void status_post_select(struct sched *s, struct task *t) { struct status_task *st = t->private_data; - int ret; t->ret = 1; if (st->fd < 0 || !FD_ISSET(st->fd, &s->rfds)) return; - ret = read(st->fd, st->buf + st->loaded, - STRINGSIZE - 1 - st->loaded); - if (ret <= 0) { - close_stat_pipe(); - /* avoid busy loop if server is down */ - while (sleep(1) > 0) /* FIXME */ - ; /* try again*/ - } else { - st->buf[ret + st->loaded] = '\0'; - st->loaded = for_each_line(st->buf, ret + st->loaded, - &check_stat_line); + t->ret = read(st->fd, st->buf + st->loaded, STRINGSIZE - 1 - st->loaded); + if (t->ret <= 0) { + if (!t->ret) + t->ret = -E_STATUS_EOF; + return; } + st->buf[t->ret + st->loaded] = '\0'; + st->loaded = for_each_line(st->buf, t->ret + st->loaded, + &check_stat_line); } static void init_status_task(struct status_task *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; diff --git a/error.h b/error.h index b08a31ec..430c12f9 100644 --- a/error.h +++ b/error.h @@ -82,12 +82,17 @@ enum para_subsystem { #define ORTP_SEND_ERRORS #define GUI_ERRORS #define RINGBUFFER_ERRORS -#define SCHED_ERRORS + extern const char **para_errlist[]; /** \endcond */ +#define SCHED_ERRORS \ + PARA_ERROR(TASK_KILLED, "task killed"), \ + PARA_ERROR(NO_SUCH_TASK, "task not found"), \ + + #define STDIN_ERRORS \ PARA_ERROR(STDIN_READ, "failed to read from stdin"), \ PARA_ERROR(STDIN_EOF, "end of file"), \ @@ -149,6 +154,8 @@ extern const char **para_errlist[]; PARA_ERROR(CLIENT_WRITE, "client write error"), \ PARA_ERROR(UCRED_PERM, "permission denied"), \ PARA_ERROR(INVALID_AUDIOD_CMD, "invalid command"), \ + PARA_ERROR(AUDIOD_SYNTAX, "syntax error"), \ + PARA_ERROR(STATUS_EOF, "server closed status connection"), \ #define FILTER_CHAIN_ERRORS \ diff --git a/sched.c b/sched.c index 9356dd0c..879ab808 100644 --- a/sched.c +++ b/sched.c @@ -106,5 +106,49 @@ void sched_shutdown(void) unregister_task(t); }; +char *get_task_list(void) +{ + struct task *t, *tmp; + char *msg = NULL; + list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) { + char *tmp_msg; + tmp_msg = make_message("%s%p\t%s\n", msg? msg : "", t, t->status); + free(msg); + msg = tmp_msg; + } + list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) { + char *tmp_msg; + if (t->pre_select) + continue; + tmp_msg = make_message("%s%p\t%s\n", msg? msg : "", t, t->status); + free(msg); + msg = tmp_msg; + } + //PARA_DEBUG_LOG("task list:\n%s", msg); + return msg; +} -//char *get_tast_list(); +int kill_task(char *id) +{ + struct task *t, *tmp; + char buf[20]; + list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) { + sprintf(buf, "%p", t); + if (strcmp(id, buf)) + continue; + t->ret = -E_TASK_KILLED; + if (t->event_handler) + t->event_handler(t); + return 1; + } + list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) { + sprintf(buf, "%p", t); + if (strcmp(id, buf)) + continue; + t->ret = -E_TASK_KILLED; + if (t->event_handler) + t->event_handler(t); + return 1; + } + return -E_NO_SUCH_TASK; +} diff --git a/sched.h b/sched.h index 9855475d..0363f0d1 100644 --- a/sched.h +++ b/sched.h @@ -27,3 +27,5 @@ void *register_task(struct task *t); void unregister_task(struct task *t); int sched(struct sched *s); void init_sched(void); +char *get_task_list(void); +int kill_task(char *id); -- 2.39.5