Merge branch 't/audiod_exit_cleanup'
authorAndre Noll <maan@tuebingen.mpg.de>
Sun, 26 Oct 2014 12:11:41 +0000 (13:11 +0100)
committerAndre Noll <maan@tuebingen.mpg.de>
Sun, 26 Oct 2014 12:14:05 +0000 (13:14 +0100)
Cooked for two months.

* t/audiod_exit_cleanup:
  audiod: Clean up by notifying tasks.

NEWS
audiod.c
audiod_command.c
error.h

diff --git a/NEWS b/NEWS
index 6ff788bf06107d4c2d18c54b543ce775840b3583..305d9147b2f0be1a3f02697be4a769fed2024449 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,7 @@ NEWS
        - Improved error diagnostics for the mvblob commands.
        - New sender subcommand: status.
        - Improved help text for server and afs commands.
+       - audiod memory leak fixes.
 
 Download: ./releases/paraslash-git.tar.bz2
 
index a072071c199d6fd3f90bb9448101ff62790c9db4..d9df3847b61c1ff93f7fcf8389ccb90baadff17e 100644 (file)
--- a/audiod.c
+++ b/audiod.c
@@ -1006,16 +1006,22 @@ static void signal_pre_select(struct sched *s, void *context)
        para_fd_set(st->fd, &s->rfds, &s->max_fileno);
 }
 
-static int signal_post_select(struct sched *s, __a_unused void *context)
+static int signal_post_select(struct sched *s, void *context)
 {
-       int signum;
+       struct signal_task *st = context;
+       int ret, 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 +1040,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 +1153,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 +1167,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 +1231,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 +1250,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) {
@@ -1435,8 +1443,10 @@ int main(int argc, char *argv[])
        sched.default_timeout.tv_sec = 2;
        sched.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&sched);
+       audiod_cleanup();
        sched_shutdown(&sched);
 
-       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;
 }
index d5c53bf90059101cd345254e0a3c294c3df73307..2aae0d805e8286303a43df96b8a172b73e21e093 100644 (file)
@@ -376,10 +376,10 @@ static int com_grab(int fd, int argc, char **argv)
        return grab_client_new(fd, argc, argv, &sched);
 }
 
-__noreturn static int com_term(int fd, __a_unused int argc, __a_unused char **argv)
+static int com_term(int fd, __a_unused int argc, __a_unused char **argv)
 {
        close(fd);
-       clean_exit(EXIT_SUCCESS, "terminating on user request");
+       return -E_AUDIOD_TERM;
 }
 
 static int com_on(int fd, __a_unused int argc, __a_unused char **argv)
diff --git a/error.h b/error.h
index 05e7e57ead5478a26ebcfb7d5573ade5879ea607..c28a25a39bf7da44bfb20d330765912d8912ba6b 100644 (file)
--- a/error.h
+++ b/error.h
@@ -343,6 +343,8 @@ extern const char **para_errlist[];
        PARA_ERROR(NOT_PLAYING, "not playing"), \
        PARA_ERROR(AUDIOD_OFF, "audiod switched off"), \
        PARA_ERROR(STATUS_TIMEOUT, "status item timeout"), \
+       PARA_ERROR(AUDIOD_SIGNAL, "caught deadly signal"), \
+       PARA_ERROR(AUDIOD_TERM, "terminating on user request"), \
 
 
 #define AUDIOD_COMMAND_ERRORS \