@@ -78,6 +78,7 @@ static bool opt_unshare_cgroup_try = false;
7878static bool opt_needs_devpts = false;
7979static bool opt_new_session = false;
8080static bool opt_die_with_parent = false;
81+ static bool opt_forward_signals = false;
8182static uid_t opt_sandbox_uid = -1 ;
8283static gid_t opt_sandbox_gid = -1 ;
8384static int opt_sync_fd = -1 ;
@@ -373,6 +374,7 @@ usage (int ecode, FILE *out)
373374 " --perms OCTAL Set permissions of next argument (--bind-data, --file, etc.)\n"
374375 " --size BYTES Set size of next argument (only for --tmpfs)\n"
375376 " --chmod OCTAL PATH Change permissions of PATH (must already exist)\n"
377+ " --forward-signals Forward various commonly used signals to the child process.\n"
376378 );
377379 exit (ecode );
378380}
@@ -387,22 +389,30 @@ handle_die_with_parent (void)
387389 die_with_error ("prctl" );
388390}
389391
392+ static int forwarded_signals [] =
393+ {
394+ SIGINT ,
395+ SIGTERM ,
396+ SIGCONT ,
397+ SIGHUP ,
398+ SIGQUIT ,
399+ SIGUSR1 ,
400+ SIGUSR2 ,
401+ SIGWINCH ,
402+ };
403+
390404static void
391- gate_signals ( int action , sigset_t * prevmask )
405+ block_forwarded_signals ( sigset_t * prevmask )
392406{
393407 sigset_t mask ;
394-
395- /* When unblocking, only restore if not previously blocked. */
408+ size_t i ;
396409
397410 sigemptyset (& mask );
398411
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 );
412+ for (i = 0 ; i < N_ELEMENTS (forwarded_signals ); i ++ )
413+ sigaddset (& mask , forwarded_signals [i ]);
404414
405- if (sigprocmask (action , & mask , prevmask ) == -1 )
415+ if (sigprocmask (SIG_BLOCK , & mask , prevmask ) == -1 )
406416 die_with_error ("sigprocmask" );
407417}
408418
@@ -527,6 +537,7 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
527537 int exitc ;
528538 pid_t died_pid ;
529539 int died_status ;
540+ size_t i ;
530541
531542 /* Close all extra fds in the monitoring process.
532543 Any passed in fds have been passed on to the child anyway. */
@@ -541,8 +552,9 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
541552
542553 sigemptyset (& mask );
543554 sigaddset (& mask , SIGCHLD );
544- sigaddset (& mask , SIGINT );
545- sigaddset (& mask , SIGTERM );
555+
556+ for (i = 0 ; i < N_ELEMENTS (forwarded_signals ); i ++ )
557+ sigaddset (& mask , forwarded_signals [i ]);
546558
547559 signal_fd = signalfd (-1 , & mask , SFD_CLOEXEC | SFD_NONBLOCK );
548560 if (signal_fd == -1 )
@@ -590,8 +602,12 @@ monitor_child (int event_fd, pid_t child_pid, int setup_finished_fd)
590602
591603 /* Propagate signal to child so that it will take the correct
592604 * 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" );
605+ if (fdsi .ssi_signo != SIGCHLD )
606+ {
607+ s = kill (child_pid , fdsi .ssi_signo );
608+ if (s != 0 && s != ESRCH )
609+ die_with_error ("kill child" );
610+ }
595611
596612 /* We may actually get several sigchld compressed into one
597613 SIGCHLD, so we have to handle all of them. */
@@ -2768,6 +2784,10 @@ parse_args_recurse (int *argcp,
27682784 argc -= 1 ;
27692785 break ;
27702786 }
2787+ else if (strcmp (arg , "--forward-signals" ) == 0 )
2788+ {
2789+ opt_forward_signals = true;
2790+ }
27712791 else if (* arg == '-' )
27722792 {
27732793 die ("Unknown option %s" , arg );
@@ -2915,7 +2935,8 @@ main (int argc,
29152935 int intermediate_pids_sockets [2 ] = {-1 , -1 };
29162936 const char * exec_path = NULL ;
29172937 int i ;
2918- sigset_t sigmask ;
2938+ sigset_t sigmask_before_forwarding ;
2939+ sigemptyset (& sigmask_before_forwarding );
29192940
29202941 /* Handle --version early on before we try to acquire/drop
29212942 * any capabilities so it works in a build environment;
@@ -3090,7 +3111,8 @@ main (int argc,
30903111 block_sigchild ();
30913112
30923113 /* We block other signals here to avoid leaving an orphan. */
3093- gate_signals (SIG_BLOCK , & sigmask );
3114+ if (opt_forward_signals )
3115+ block_forwarded_signals (& sigmask_before_forwarding );
30943116
30953117 clone_flags = SIGCHLD | CLONE_NEWNS ;
30963118 if (opt_unshare_user )
@@ -3242,8 +3264,12 @@ main (int argc,
32423264 return monitor_child (event_fd , pid , setup_finished_pipe [0 ]);
32433265 }
32443266
3245- /* Unblock other signals here to receive signals from the parent. */
3246- gate_signals (SIG_UNBLOCK , & sigmask );
3267+ /* Restore the state of sigmask from before the blocking. */
3268+ if (opt_forward_signals )
3269+ {
3270+ if (sigprocmask (SIG_SETMASK , & sigmask_before_forwarding , NULL ) != 0 )
3271+ die_with_error ("sigprocmask" );
3272+ }
32473273
32483274 if (opt_pidns_fd > 0 )
32493275 {
0 commit comments