]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - audiod.c
Improve signal init and shutdown.
[paraslash.git] / audiod.c
index a072071c199d6fd3f90bb9448101ff62790c9db4..3f83b984a8215208e1247aade01e06c421e745a6 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005-2014 Andre Noll <maan@tuebingen.mpg.de>
+ * Copyright (C) 2005 Andre Noll <maan@tuebingen.mpg.de>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -144,7 +144,7 @@ struct audiod_args_info conf;
 static char *socket_name;
 static struct audio_format_info afi[NUM_AUDIO_FORMATS];
 
-static struct signal_task signal_task_struct, *sig_task = &signal_task_struct;
+static struct signal_task *signal_task;
 
 static struct status_task status_task_struct;
 
@@ -310,17 +310,6 @@ empty:
        return para_strdup(NULL);
 }
 
-static int want_colors(void)
-{
-       if (conf.color_arg == color_arg_no)
-               return 0;
-       if (conf.color_arg == color_arg_yes)
-               return 1;
-       if (conf.logfile_given)
-               return 0;
-       return isatty(STDERR_FILENO);
-}
-
 static void parse_config_or_die(void)
 {
        int ret;
@@ -358,8 +347,7 @@ err:
 
 static void setup_signal_handling(void)
 {
-       sig_task->fd = para_signal_init();
-       PARA_INFO_LOG("signal pipe: fd %d\n", sig_task->fd);
+       signal_task = signal_init_or_die();
        para_install_sighandler(SIGINT);
        para_install_sighandler(SIGTERM);
        para_install_sighandler(SIGHUP);
@@ -390,6 +378,7 @@ static void close_receiver(int slot_num)
        task_reap(&s->receiver_node->task);
        free(s->receiver_node);
        s->receiver_node = NULL;
+       stat_task->current_audio_format_num = -1;
        tv_add(now, &(struct timeval)EMBRACE(0, 200 * 1000),
                &a->restart_barrier);
 }
@@ -1000,22 +989,22 @@ err:
        exit(EXIT_FAILURE);
 }
 
-static void signal_pre_select(struct sched *s, void *context)
+static int signal_post_select(struct sched *s, void *context)
 {
        struct signal_task *st = context;
-       para_fd_set(st->fd, &s->rfds, &s->max_fileno);
-}
+       int ret, signum;
 
-static int signal_post_select(struct sched *s, __a_unused void *context)
-{
-       int signum;
+       ret = task_get_notification(st->task);
+       if (ret < 0)
+               return ret;
        signum = para_next_signal(&s->rfds);
        switch (signum) {
        case SIGINT:
        case SIGTERM:
        case SIGHUP:
                PARA_NOTICE_LOG("received signal %d\n", signum);
-               clean_exit(EXIT_FAILURE, "caught deadly signal");
+               task_notify_all(s, E_AUDIOD_SIGNAL);
+               return -E_AUDIOD_SIGNAL;
        }
        return 0;
 }
@@ -1034,10 +1023,17 @@ static int command_post_select(struct sched *s, void *context)
        struct timeval tmp, delay;
        bool force = true;
 
-       ret = handle_connect(ct->fd, &s->rfds);
+       ret = task_get_notification(ct->task);
        if (ret < 0)
+               return ret;
+       ret = handle_connect(ct->fd, &s->rfds);
+       if (ret < 0) {
                PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-       else if (ret > 0)
+               if (ret == -E_AUDIOD_TERM) {
+                       task_notify_all(s, -ret);
+                       return ret;
+               }
+       } else if (ret > 0)
                goto dump;
 
        /* if last status dump was less than 500ms ago, do nothing */
@@ -1140,19 +1136,13 @@ static void close_unused_slots(void)
                        close_slot(i);
 }
 
-/**
- * Close the connection to para_server and exit.
- *
- * \param status The exit status which is passed to exit(3).
- * \param msg The log message
- *
- * Log \a msg with loglevel \p EMERG, close the connection to para_server and
- * all slots, and call \p exit(status). \a status should be either EXIT_SUCCESS
- * or EXIT_FAILURE.
+/*
+ * Cleanup all resources.
  *
- * \sa exit(3).
+ * This performs various cleanups, removes the audiod socket and closes the
+ * connection to para_server.
  */
-void __noreturn clean_exit(int status, const char *msg)
+static void audiod_cleanup(void)
 {
        if (socket_name)
                unlink(socket_name);
@@ -1160,8 +1150,6 @@ void __noreturn clean_exit(int status, const char *msg)
        close_unused_slots();
        audiod_cmdline_parser_free(&conf);
        close_stat_clients();
-       PARA_EMERG_LOG("%s\n", msg);
-       exit(status);
 }
 
 /*
@@ -1226,7 +1214,11 @@ min_delay:
 static int status_post_select(struct sched *s, void *context)
 {
        struct status_task *st = context;
+       int ret;
 
+       ret = task_get_notification(st->task);
+       if (ret < 0)
+               return ret;
        if (audiod_status == AUDIOD_OFF) {
                if (!st->ct)
                        goto out;
@@ -1241,7 +1233,6 @@ static int status_post_select(struct sched *s, void *context)
        if (st->ct) {
                char *buf;
                size_t sz;
-               int ret;
 
                ret = btr_node_status(st->btrn, st->min_iqs, BTR_NT_LEAF);
                if (ret < 0) {
@@ -1350,18 +1341,6 @@ __noreturn static void print_help_and_die(void)
        exit(0);
 }
 
-static void init_colors_or_die(void)
-{
-       int i;
-
-       if (!want_colors())
-               return;
-       daemon_set_default_log_colors();
-       daemon_set_flag(DF_COLOR_LOG);
-       for (i = 0; i < conf.log_color_given; i++)
-               daemon_set_log_color_or_die(conf.log_color_arg[i]);
-}
-
 /**
  * the main function of para_audiod
  *
@@ -1396,7 +1375,8 @@ int main(int argc, char *argv[])
                print_help_and_die();
        daemon_drop_privileges_or_die(conf.user_arg, conf.group_arg);
        parse_config_or_die();
-       init_colors_or_die();
+       daemon_init_colors_or_die(conf.color_arg, color_arg_auto, color_arg_no,
+               conf.logfile_given, conf.log_color_arg, conf.log_color_given);
        init_random_seed_or_die();
        daemon_set_flag(DF_LOG_TIME);
        daemon_set_flag(DF_LOG_HOSTNAME);
@@ -1425,18 +1405,21 @@ int main(int argc, char *argv[])
        if (conf.daemon_given)
                daemonize(false /* parent exits immediately */);
 
-       sig_task->task = task_register(&(struct task_info) {
+       signal_task->task = task_register(&(struct task_info) {
                .name = "signal",
                .pre_select = signal_pre_select,
                .post_select = signal_post_select,
-               .context = sig_task,
+               .context = signal_task,
        }, &sched);
 
        sched.default_timeout.tv_sec = 2;
        sched.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&sched);
+       audiod_cleanup();
        sched_shutdown(&sched);
+       signal_shutdown(signal_task);
 
-       PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       return EXIT_FAILURE;
+       if (ret < 0)
+               PARA_EMERG_LOG("%s\n", para_strerror(-ret));
+       return ret < 0? EXIT_FAILURE : EXIT_SUCCESS;
 }