From c29457cf28486bc455c437e300bcfd0c7582c605 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Wed, 12 Oct 2011 18:13:40 +0200 Subject: [PATCH] server: Kill temporary SIGCHLD handler. 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 | 16 ++++++---------- signal.c | 40 ++++++++++++++++++++++++++++++++++++++++ signal.h | 2 ++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/server.c b/server.c index 6b1e11d6..1e45eb36 100644 --- 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"); diff --git a/signal.c b/signal.c index 2d5549d5..aa63c8b5 100644 --- 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. * diff --git a/signal.h b/signal.h index 799c317f..266b3aba 100644 --- 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); -- 2.39.5