diff options
author | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-05-31 04:14:51 +0200 |
---|---|---|
committer | Matthias Schiffer <mschiffer@universe-factory.net> | 2014-05-31 04:14:51 +0200 |
commit | 060c91156379c07fc714bc1c4de2a88a9ff9daa0 (patch) | |
tree | 3ce2128606c5746d0cd2af9b0cc7ee8a7778b8e0 /src | |
parent | 404785fe4a7cfc1a9a6cd9d2a9885a69992ff1ce (diff) | |
download | fastd-060c91156379c07fc714bc1c4de2a88a9ff9daa0.tar fastd-060c91156379c07fc714bc1c4de2a88a9ff9daa0.zip |
Fix signal handling races
Diffstat (limited to 'src')
-rw-r--r-- | src/fastd.c | 54 |
1 files changed, 30 insertions, 24 deletions
diff --git a/src/fastd.c b/src/fastd.c index 3bc3929..522d4b6 100644 --- a/src/fastd.c +++ b/src/fastd.c @@ -69,6 +69,7 @@ fastd_context_t ctx; static volatile bool sighup = false; /**< Is set to true when a SIGHUP is received */ static volatile bool terminate = false; /**< Is set to true when a SIGTERM, SIGQUIT or SIGINT is received */ static volatile bool dump = false; /**< Is set to true when a SIGUSR1 is received */ +static volatile bool sigchld = false; /**< Is set to true when a SIGCHLD is received */ /** SIGHUP handler */ @@ -86,30 +87,9 @@ static void on_sigusr1(int signo UNUSED) { dump = true; } -/** - SIGCHLD handler - - Reaps zombies of asynchronous shell commands. -*/ +/** SIGCHLD handler */ static void on_sigchld(int signo UNUSED) { - size_t i; - for (i = 0; i < VECTOR_LEN(ctx.async_pids);) { - pid_t pid = VECTOR_INDEX(ctx.async_pids, i); - if (waitpid(pid, NULL, WNOHANG) > 0) { - pr_debug("child process %u finished", (unsigned)pid); - } - else { - if (errno == ECHILD) { - i++; - continue; - } - else { - pr_error_errno("waitpid"); - } - } - - VECTOR_DELETE(ctx.async_pids, i); - } + sigchld = true; } /** Installs signal handlers */ @@ -308,6 +288,27 @@ static inline void maintenance(void) { ctx.next_maintenance.tv_sec += MAINTENANCE_INTERVAL; } +/** Reaps zombies of asynchronous shell commands. */ +static inline void reap_zombies(void) { + size_t i; + for (i = 0; i < VECTOR_LEN(ctx.async_pids);) { + pid_t pid = VECTOR_INDEX(ctx.async_pids, i); + if (waitpid(pid, NULL, WNOHANG) > 0) { + pr_debug("child process %u finished", (unsigned)pid); + } + else { + if (errno == ECHILD) { + i++; + continue; + } + else { + pr_error_errno("waitpid"); + } + } + + VECTOR_DELETE(ctx.async_pids, i); + } +} /** Closes all open FDs except stdin, stdout and stderr */ void fastd_close_all_fds(void) { @@ -616,7 +617,7 @@ int main(int argc, char *argv[]) { maintenance(); sigset_t set, oldset; - sigemptyset(&set); + sigfillset(&set); pthread_sigmask(SIG_SETMASK, &set, &oldset); if (sighup) { @@ -633,6 +634,11 @@ int main(int argc, char *argv[]) { dump_state(); } + if (sigchld) { + sigchld = false; + reap_zombies(); + } + pthread_sigmask(SIG_SETMASK, &oldset, NULL); } |