server: Kill temporary SIGCHLD handler.
authorAndre Noll <maan@systemlinux.org>
Wed, 12 Oct 2011 16:13:40 +0000 (18:13 +0200)
committerAndre Noll <maan@systemlinux.org>
Sat, 15 Oct 2011 19:22:53 +0000 (21:22 +0200)
During startup, para_server sets up a temporary signal handler for
SIGCHLD in order to notice if the afs child process terminates
immediately (doing the signal setup after the fork would be too
late). This patch makes it block this signal during this period
instead. This works equally well and it fixes a weird problem on Mac
OS where the temporary SIGCHLD handler was executed although it had
been replaced by the generic signal handler of signal.c.

server.c
signal.c
signal.h

index 6b1e11d..1e45eb3 100644 (file)
--- a/server.c
+++ b/server.c
@@ -462,12 +462,6 @@ static int init_afs(void)
        return afs_server_socket[0];
 }
 
-__noreturn static void tmp_sigchld_handler(__a_unused int s)
-{
-       PARA_EMERG_LOG("caught early SIGCHLD\n");
-       exit(EXIT_FAILURE);
-}
-
 static void server_init(int argc, char **argv)
 {
        struct server_cmdline_parser_params params = {
@@ -509,14 +503,16 @@ static void server_init(int argc, char **argv)
         */
        para_sigaction(SIGUSR1, SIG_IGN);
        /*
-        * We have to install a SIGCHLD handler before the afs process is being
-        * forked off. Otherwise, para_server does not notice if afs dies before
-        * the SIGCHLD handler has been installed by init_signal_task() below.
+        * We have to block SIGCHLD before the afs process is being forked off.
+        * Otherwise, para_server does not notice if afs dies before the
+        * SIGCHLD handler has been installed for the parent process by
+        * init_signal_task() below.
         */
-       para_sigaction(SIGCHLD, tmp_sigchld_handler);
+       para_block_signal(SIGCHLD);
        PARA_NOTICE_LOG("initializing the audio file selector\n");
        afs_socket = init_afs();
        init_signal_task();
+       para_unblock_signal(SIGCHLD);
        PARA_NOTICE_LOG("initializing virtual streaming system\n");
        init_vss_task(afs_socket);
        PARA_NOTICE_LOG("server init complete\n");
index 2d5549d..aa63c8b 100644 (file)
--- a/signal.c
+++ b/signal.c
@@ -147,6 +147,46 @@ void para_install_sighandler(int sig)
        para_sigaction(sig, &generic_signal_handler);
 }
 
+/**
+ * Block a signal for the caller.
+ *
+ * \param sig The signal to block.
+ *
+ * This sets the given signal in the current signal mask of the calling process
+ * to prevent this signal from delivery.
+ *
+ * \sa \ref para_unblock_signal(), sigprocmask(2), sigaddset(3).
+ */
+void para_block_signal(int sig)
+{
+       sigset_t set;
+
+       PARA_DEBUG_LOG("blocking signal %d\n", sig);
+       sigemptyset(&set);
+       sigaddset(&set, sig);
+       sigprocmask(SIG_BLOCK, &set, NULL);
+}
+
+/**
+ * Unblock a signal.
+ *
+ * \param sig The signal to unblock.
+ *
+ * This function removes the given signal from the current set of blocked
+ * signals.
+ *
+ * \sa \ref para_block_signal(), sigprocmask(2), sigaddset(3).
+ */
+void para_unblock_signal(int sig)
+{
+       sigset_t set;
+
+       PARA_DEBUG_LOG("unblocking signal %d\n", sig);
+       sigemptyset(&set);
+       sigaddset(&set, sig);
+       sigprocmask(SIG_UNBLOCK, &set, NULL);
+}
+
 /**
  * Return the number of the next pending signal.
  *
index 799c317..266b3ab 100644 (file)
--- a/signal.h
+++ b/signal.h
@@ -22,3 +22,5 @@ void para_install_sighandler(int);
 int para_reap_child(pid_t *pid);
 int para_next_signal(fd_set *rfds);
 void para_signal_shutdown(void);
+void para_block_signal(int sig);
+void para_unblock_signal(int sig);