@@ -387,6 +387,25 @@ handle_die_with_parent (void)
387387 die_with_error ("prctl" );
388388}
389389
390+ static void
391+ gate_signals (int action , sigset_t * prevmask )
392+ {
393+ sigset_t mask ;
394+
395+ /* When unblocking, only restore if not previously blocked. */
396+
397+ sigemptyset (& mask );
398+
399+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGINT ))
400+ sigaddset (& mask , SIGINT );
401+
402+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGTERM ))
403+ sigaddset (& mask , SIGTERM );
404+
405+ if (sigprocmask (action , & mask , prevmask ) == -1 )
406+ die_with_error ("sigprocmask" );
407+ }
408+
390409static void
391410block_sigchild (void )
392411{
@@ -522,6 +541,8 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
522541
523542 sigemptyset (& mask );
524543 sigaddset (& mask , SIGCHLD );
544+ sigaddset (& mask , SIGINT );
545+ sigaddset (& mask , SIGTERM );
525546
526547 signal_fd = signalfd (-1 , & mask , SFD_CLOEXEC | SFD_NONBLOCK );
527548 if (signal_fd == -1 )
@@ -561,12 +582,17 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
561582 }
562583
563584 /* We need to read the signal_fd, or it will keep polling as read,
564- * however we ignore the details as we get them from waitpid
585+ * however we ignore the details for SIGCHLD as we get them from waitpid
565586 * below anyway */
566587 s = read (signal_fd , & fdsi , sizeof (struct signalfd_siginfo ));
567588 if (s == -1 && errno != EINTR && errno != EAGAIN )
568589 die_with_error ("read signalfd" );
569590
591+ /* Propagate signal to child so that it will take the correct
592+ * action. This avoids the parent terminating, leaving an orphan. */
593+ if (fdsi .ssi_signo != SIGCHLD && kill (child_pid , fdsi .ssi_signo ))
594+ die_with_error ("kill child" );
595+
570596 /* We may actually get several sigchld compressed into one
571597 SIGCHLD, so we have to handle all of them. */
572598 while ((died_pid = waitpid (-1 , & died_status , WNOHANG )) > 0 )
@@ -2889,6 +2915,7 @@ main (int argc,
28892915 int intermediate_pids_sockets [2 ] = {-1 , -1 };
28902916 const char * exec_path = NULL ;
28912917 int i ;
2918+ sigset_t sigmask ;
28922919
28932920 /* Handle --version early on before we try to acquire/drop
28942921 * any capabilities so it works in a build environment;
@@ -3062,6 +3089,9 @@ main (int argc,
30623089 /* We block sigchild here so that we can use signalfd in the monitor. */
30633090 block_sigchild ();
30643091
3092+ /* We block other signals here to avoid leaving an orphan. */
3093+ gate_signals (SIG_BLOCK , & sigmask );
3094+
30653095 clone_flags = SIGCHLD | CLONE_NEWNS ;
30663096 if (opt_unshare_user )
30673097 clone_flags |= CLONE_NEWUSER ;
@@ -3212,6 +3242,9 @@ main (int argc,
32123242 return monitor_child (event_fd , pid , setup_finished_pipe [0 ]);
32133243 }
32143244
3245+ /* Unblock other signals here to receive signals from the parent. */
3246+ gate_signals (SIG_UNBLOCK , & sigmask );
3247+
32153248 if (opt_pidns_fd > 0 )
32163249 {
32173250 if (setns (opt_pidns_fd , CLONE_NEWPID ) != 0 )
0 commit comments