@@ -379,6 +379,25 @@ handle_die_with_parent (void)
379379 die_with_error ("prctl" );
380380}
381381
382+ static void
383+ gate_signals (int action , sigset_t * prevmask )
384+ {
385+ sigset_t mask ;
386+
387+ /* When unblocking, only restore if not previously blocked. */
388+
389+ sigemptyset (& mask );
390+
391+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGINT ))
392+ sigaddset (& mask , SIGINT );
393+
394+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGTERM ))
395+ sigaddset (& mask , SIGTERM );
396+
397+ if (sigprocmask (action , & mask , prevmask ) == -1 )
398+ die_with_error ("sigprocmask" );
399+ }
400+
382401static void
383402block_sigchild (void )
384403{
@@ -514,6 +533,8 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
514533
515534 sigemptyset (& mask );
516535 sigaddset (& mask , SIGCHLD );
536+ sigaddset (& mask , SIGINT );
537+ sigaddset (& mask , SIGTERM );
517538
518539 signal_fd = signalfd (-1 , & mask , SFD_CLOEXEC | SFD_NONBLOCK );
519540 if (signal_fd == -1 )
@@ -553,12 +574,17 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
553574 }
554575
555576 /* We need to read the signal_fd, or it will keep polling as read,
556- * however we ignore the details as we get them from waitpid
577+ * however we ignore the details for SIGCHLD as we get them from waitpid
557578 * below anyway */
558579 s = read (signal_fd , & fdsi , sizeof (struct signalfd_siginfo ));
559580 if (s == -1 && errno != EINTR && errno != EAGAIN )
560581 die_with_error ("read signalfd" );
561582
583+ /* Propagate signal to child so that it will take the correct
584+ * action. This avoids the parent terminating, leaving an orphan. */
585+ if (fdsi .ssi_signo != SIGCHLD && kill (child_pid , fdsi .ssi_signo ))
586+ die_with_error ("kill child" );
587+
562588 /* We may actually get several sigchld compressed into one
563589 SIGCHLD, so we have to handle all of them. */
564590 while ((died_pid = waitpid (-1 , & died_status , WNOHANG )) > 0 )
@@ -2641,6 +2667,7 @@ main (int argc,
26412667 int res UNUSED ;
26422668 cleanup_free char * args_data UNUSED = NULL ;
26432669 int intermediate_pids_sockets [2 ] = {-1 , -1 };
2670+ sigset_t sigmask ;
26442671
26452672 /* Handle --version early on before we try to acquire/drop
26462673 * any capabilities so it works in a build environment;
@@ -2814,6 +2841,9 @@ main (int argc,
28142841 /* We block sigchild here so that we can use signalfd in the monitor. */
28152842 block_sigchild ();
28162843
2844+ /* We block other signals here to avoid leaving an orphan. */
2845+ gate_signals (SIG_BLOCK , & sigmask );
2846+
28172847 clone_flags = SIGCHLD | CLONE_NEWNS ;
28182848 if (opt_unshare_user )
28192849 clone_flags |= CLONE_NEWUSER ;
@@ -2964,6 +2994,9 @@ main (int argc,
29642994 return monitor_child (event_fd , pid , setup_finished_pipe [0 ]);
29652995 }
29662996
2997+ /* Unblock other signals here to receive signals from the parent. */
2998+ gate_signals (SIG_UNBLOCK , & sigmask );
2999+
29673000 if (opt_pidns_fd > 0 )
29683001 {
29693002 if (setns (opt_pidns_fd , CLONE_NEWPID ) != 0 )
0 commit comments