Fix afs signal handling.
authorAndre Noll <maan@systemlinux.org>
Tue, 25 Mar 2008 07:47:34 +0000 (08:47 +0100)
committerAndre Noll <maan@systemlinux.org>
Tue, 25 Mar 2008 07:47:34 +0000 (08:47 +0100)
afs must not abort on SIGPIPE as the client may close the
connection at any time. This bug was there forever but showed
up only now because the recent callback changes made the afs
process write to the command handler socket multiple times.

Also ignore SIGUSR1 instead of catching and ignoring it.

afs.c

diff --git a/afs.c b/afs.c
index d7c1ecf..451a492 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -771,8 +771,6 @@ static void signal_post_select(struct sched *s, struct task *t)
                return;
        st->signum = para_next_signal();
        t->ret = 1;
                return;
        st->signum = para_next_signal();
        t->ret = 1;
-       if (st->signum == SIGUSR1)
-               return; /* ignore SIGUSR1 */
        if (st->signum == SIGHUP) {
                close_afs_tables();
                t->ret = open_afs_tables();
        if (st->signum == SIGHUP) {
                close_afs_tables();
                t->ret = open_afs_tables();
@@ -790,11 +788,19 @@ err:
 static void register_signal_task(void)
 {
        struct signal_task *st = &signal_task_struct;
 static void register_signal_task(void)
 {
        struct signal_task *st = &signal_task_struct;
+
+       if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) {
+               PARA_EMERG_LOG("failed to ignore SIGPIPE\n");
+               exit(EXIT_FAILURE);
+       }
+       if (signal(SIGUSR1, SIG_IGN) == SIG_ERR) {
+               PARA_EMERG_LOG("failed to ignore SIGUSR1\n");
+               exit(EXIT_FAILURE);
+       }
        st->fd = para_signal_init();
        PARA_INFO_LOG("signal pipe: fd %d\n", st->fd);
        para_install_sighandler(SIGINT);
        para_install_sighandler(SIGTERM);
        st->fd = para_signal_init();
        PARA_INFO_LOG("signal pipe: fd %d\n", st->fd);
        para_install_sighandler(SIGINT);
        para_install_sighandler(SIGTERM);
-       para_install_sighandler(SIGPIPE);
        para_install_sighandler(SIGHUP);
 
        st->task.pre_select = signal_pre_select;
        para_install_sighandler(SIGHUP);
 
        st->task.pre_select = signal_pre_select;
@@ -1018,12 +1024,6 @@ static void register_command_task(uint32_t cookie)
        register_task(&ct->task);
 }
 
        register_task(&ct->task);
 }
 
-static void register_tasks(uint32_t cookie)
-{
-       register_signal_task();
-       register_command_task(cookie);
-}
-
 /**
  * Initialize the audio file selector process.
  *
 /**
  * Initialize the audio file selector process.
  *
@@ -1035,29 +1035,29 @@ __noreturn void afs_init(uint32_t cookie, int socket_fd)
        struct sched s;
        int i, ret;
 
        struct sched s;
        int i, ret;
 
+       register_signal_task();
        INIT_LIST_HEAD(&afs_client_list);
        for (i = 0; i < NUM_AFS_TABLES; i++)
                afs_tables[i].init(&afs_tables[i]);
        ret = open_afs_tables();
        INIT_LIST_HEAD(&afs_client_list);
        for (i = 0; i < NUM_AFS_TABLES; i++)
                afs_tables[i].init(&afs_tables[i]);
        ret = open_afs_tables();
-
-       if (ret < 0) {
-               PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-               exit(EXIT_FAILURE);
-       }
+       if (ret < 0)
+               goto out;
        server_socket = socket_fd;
        ret = mark_fd_nonblocking(server_socket);
        if (ret < 0)
        server_socket = socket_fd;
        ret = mark_fd_nonblocking(server_socket);
        if (ret < 0)
-               exit(EXIT_FAILURE);
+               goto out_close;
        PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n",
                server_socket, (unsigned) cookie);
        init_admissible_files(conf.afs_initial_mode_arg);
        PARA_INFO_LOG("server_socket: %d, afs_socket_cookie: %u\n",
                server_socket, (unsigned) cookie);
        init_admissible_files(conf.afs_initial_mode_arg);
-       register_tasks(cookie);
+       register_command_task(cookie);
        s.default_timeout.tv_sec = 0;
        s.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&s);
        s.default_timeout.tv_sec = 0;
        s.default_timeout.tv_usec = 999 * 1000;
        ret = schedule(&s);
+out_close:
+       close_afs_tables();
+out:
        if (ret < 0)
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
        if (ret < 0)
                PARA_EMERG_LOG("%s\n", para_strerror(-ret));
-       close_afs_tables();
        exit(EXIT_FAILURE);
 }
 
        exit(EXIT_FAILURE);
 }