@@ -381,6 +381,25 @@ handle_die_with_parent (void)
381381 die_with_error ("prctl" );
382382}
383383
384+ static void
385+ gate_signals (int action , sigset_t * prevmask )
386+ {
387+ sigset_t mask ;
388+
389+ /* When unblocking, only restore if not previously blocked. */
390+
391+ sigemptyset (& mask );
392+
393+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGINT ))
394+ sigaddset (& mask , SIGINT );
395+
396+ if (action == SIG_BLOCK || !sigismember (prevmask , SIGTERM ))
397+ sigaddset (& mask , SIGTERM );
398+
399+ if (sigprocmask (action , & mask , prevmask ) == -1 )
400+ die_with_error ("sigprocmask" );
401+ }
402+
384403static void
385404block_sigchild (void )
386405{
@@ -516,6 +535,8 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
516535
517536 sigemptyset (& mask );
518537 sigaddset (& mask , SIGCHLD );
538+ sigaddset (& mask , SIGINT );
539+ sigaddset (& mask , SIGTERM );
519540
520541 signal_fd = signalfd (-1 , & mask , SFD_CLOEXEC | SFD_NONBLOCK );
521542 if (signal_fd == -1 )
@@ -555,12 +576,17 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
555576 }
556577
557578 /* We need to read the signal_fd, or it will keep polling as read,
558- * however we ignore the details as we get them from waitpid
579+ * however we ignore the details for SIGCHLD as we get them from waitpid
559580 * below anyway */
560581 s = read (signal_fd , & fdsi , sizeof (struct signalfd_siginfo ));
561582 if (s == -1 && errno != EINTR && errno != EAGAIN )
562583 die_with_error ("read signalfd" );
563584
585+ /* Propagate signal to child so that it will take the correct
586+ * action. This avoids the parent terminating, leaving an orphan. */
587+ if (fdsi .ssi_signo != SIGCHLD && kill (child_pid , fdsi .ssi_signo ))
588+ die_with_error ("kill child" );
589+
564590 /* We may actually get several sigchld compressed into one
565591 SIGCHLD, so we have to handle all of them. */
566592 while ((died_pid = waitpid (-1 , & died_status , WNOHANG )) > 0 )
@@ -2666,6 +2692,7 @@ main (int argc,
26662692 cleanup_free char * args_data UNUSED = NULL ;
26672693 int intermediate_pids_sockets [2 ] = {-1 , -1 };
26682694 const char * exec_path = NULL ;
2695+ sigset_t sigmask ;
26692696
26702697 /* Handle --version early on before we try to acquire/drop
26712698 * any capabilities so it works in a build environment;
@@ -2839,6 +2866,9 @@ main (int argc,
28392866 /* We block sigchild here so that we can use signalfd in the monitor. */
28402867 block_sigchild ();
28412868
2869+ /* We block other signals here to avoid leaving an orphan. */
2870+ gate_signals (SIG_BLOCK , & sigmask );
2871+
28422872 clone_flags = SIGCHLD | CLONE_NEWNS ;
28432873 if (opt_unshare_user )
28442874 clone_flags |= CLONE_NEWUSER ;
@@ -2989,6 +3019,9 @@ main (int argc,
29893019 return monitor_child (event_fd , pid , setup_finished_pipe [0 ]);
29903020 }
29913021
3022+ /* Unblock other signals here to receive signals from the parent. */
3023+ gate_signals (SIG_UNBLOCK , & sigmask );
3024+
29923025 if (opt_pidns_fd > 0 )
29933026 {
29943027 if (setns (opt_pidns_fd , CLONE_NEWPID ) != 0 )
0 commit comments