Note that there are some explanatory texts on larger screens.

plurals
  1. POSIGTERM to all children processes but not parent
    primarykey
    data
    text
    <p>I have a C program that operates by responding to signals. Some signals cause the parent to fork. This allows other processing while the parent continues to respond to signals.</p> <p>When the parent is sent a SIGTERM, I want the forked children to receive a SIGTERM as well. It isn't critical that the children finish handling the SIGTERM before the parent exits.</p> <p>However, with the below code, the children do not receive a SIGTERM when I call <code>kill(0, SIGTERM)</code> from the parent. From the <a href="http://linux.die.net/man/2/kill" rel="nofollow"><code>kill</code> manpage</a>, it looks like all of the children should get this SIGTERM.</p> <p>I have a signal handler setup for the parent.</p> <pre><code>static volatile sig_atomic_t done = 0; const int handled_signals[] = {SIGINT, SIGTERM, 0}; static void set_flag(int signum) { switch (signum) { /* Intentionally exclude SIGQUIT/SIGABRT/etc. as we want to exit * without cleaning up to help with debugging */ case SIGTERM: case SIGINT: done = 1; break; default: /* Should be unreachable, but just in case */ if (signal(signum, SIG_DFL) != SIG_ERR) { raise(signum); } } } static int setup_handlers() { struct sigaction sa; sigset_t block_all; int i; /* Block all other signals while handling a signal. This is okay as * our handler is very brief */ sigfillset(&amp;block_all); sa.sa_mask = block_all; sa.sa_handler = set_flag; for (i = 0; handled_signals[i] != 0; i++) { if (sigaction(handled_signals[i], &amp;sa, NULL)) { err_log("Unable to set sigaction"); return 1; } } /* Ignore SIGCHLD as we don't keep track of child success */ sa.sa_handler = SIG_IGN; if (sigaction(SIGCHLD, &amp;sa, NULL)) { err_log("Unable to ignore SIGCHLD"); return 1; } return 0; } int main() { int i; sigset_t block_mask, orig_mask; setup_handlers(); /* Block all of our handled signals as we will be using * sigsuspend in the loop below */ sigemptyset(&amp;block_mask); for (i = 0; handled_signals[i] != 0; i++) { sigaddset(&amp;block_mask, handled_signals[i]); } if (sigprocmask(SIG_BLOCK, &amp;block_mask, &amp;orig_mask)) { err_log("Error blocking signals"); } while (!done) { if (sigsuspend(&amp;orig_mask) &amp;&amp; errno != EINTR) { err_log("sigsuspend"); } } /* Kill all children */ if (kill(0, SIGTERM)) { err_log("kill(0, SIGTERM))"); } } </code></pre> <p>After getting a signal that requires a fork, I do the following</p> <pre><code>static int unregister_handlers() { struct sigaction sa; int i; sa.sa_handler = SIG_DFL; for (i = 0; handled_signals[i] != 0; i++) { if (sigaction(handled_signals[i], &amp;sa, NULL)) { err_log("sigaction unregister"); return 1; } } if (sigaction(SIGCHLD, &amp;sa, NULL)) { err_log("sigaction SIGCHLD unregister"); return 1; } return 0; } void do_fork() { switch(fork()) { /* Error */ case -1: err_log("fork"); break; /* Child */ case 0: if (unregister_handlers()) { _exit(1); } do_fork_stuff(); _exit(0); break; /* Parent */ default: break; } } </code></pre> <p>In <code>do_fork_stuff</code>, the child sleeps for 30 seconds. I then call <code>kill(0, SIGTERM)</code> from the parent. The children do not terminate.</p> <p>What's the reason the children aren't getting the SIGTERM?</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload