@@ -383,6 +383,25 @@ handle_die_with_parent (void)
383383 die_with_error ("prctl" );
384384}
385385
386+ static void
387+ gate_signals (int action , sigset_t * prevmask )
388+ {
389+ sigset_t mask ;
390+
391+ /* When unblocking, only restore if not previously blocked. */
392+
393+ sigemptyset (& mask );
394+
395+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGINT ))
396+ sigaddset (& mask , SIGINT );
397+
398+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGTERM ))
399+ sigaddset (& mask , SIGTERM );
400+
401+ if (sigprocmask (action , & mask , prevmask ) == -1 )
402+ die_with_error ("sigprocmask" );
403+ }
404+
386405static void
387406block_sigchild (void )
388407{
@@ -518,6 +537,8 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
518537
519538 sigemptyset (& mask );
520539 sigaddset (& mask , SIGCHLD );
540+ sigaddset (& mask , SIGINT );
541+ sigaddset (& mask , SIGTERM );
521542
522543 signal_fd = signalfd (-1 , & mask , SFD_CLOEXEC | SFD_NONBLOCK );
523544 if (signal_fd == -1 )
@@ -557,12 +578,17 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
557578 }
558579
559580 /* We need to read the signal_fd, or it will keep polling as read,
560- * however we ignore the details as we get them from waitpid
581+ * however we ignore the details for SIGCHLD as we get them from waitpid
561582 * below anyway */
562583 s = read (signal_fd , & fdsi , sizeof (struct signalfd_siginfo ));
563584 if (s == -1 && errno != EINTR && errno != EAGAIN )
564585 die_with_error ("read signalfd" );
565586
587+ /* Propagate signal to child so that it will take the correct
588+ * action. This avoids the parent terminating, leaving an orphan. */
589+ if (fdsi .ssi_signo != SIGCHLD && kill (child_pid , fdsi .ssi_signo ))
590+ die_with_error ("kill child" );
591+
566592 /* We may actually get several sigchld compressed into one
567593 SIGCHLD, so we have to handle all of them. */
568594 while ((died_pid = waitpid (-1 , & died_status , WNOHANG )) > 0 )
@@ -2716,6 +2742,7 @@ main (int argc,
27162742 cleanup_free char * args_data UNUSED = NULL ;
27172743 int intermediate_pids_sockets [2 ] = {-1 , -1 };
27182744 const char * exec_path = NULL ;
2745+ sigset_t sigmask ;
27192746
27202747 /* Handle --version early on before we try to acquire/drop
27212748 * any capabilities so it works in a build environment;
@@ -2889,6 +2916,9 @@ main (int argc,
28892916 /* We block sigchild here so that we can use signalfd in the monitor. */
28902917 block_sigchild ();
28912918
2919+ /* We block other signals here to avoid leaving an orphan. */
2920+ gate_signals (SIG_BLOCK , & sigmask );
2921+
28922922 clone_flags = SIGCHLD | CLONE_NEWNS ;
28932923 if (opt_unshare_user )
28942924 clone_flags |= CLONE_NEWUSER ;
@@ -3039,6 +3069,9 @@ main (int argc,
30393069 return monitor_child (event_fd , pid , setup_finished_pipe [0 ]);
30403070 }
30413071
3072+ /* Unblock other signals here to receive signals from the parent. */
3073+ gate_signals (SIG_UNBLOCK , & sigmask );
3074+
30423075 if (opt_pidns_fd > 0 )
30433076 {
30443077 if (setns (opt_pidns_fd , CLONE_NEWPID ) != 0 )
0 commit comments