From 1a7c635071d35c38a8138ee5fba80d77a6e361c1 Mon Sep 17 00:00:00 2001 From: Chris Kuehl Date: Tue, 14 Jun 2016 11:34:52 -0700 Subject: [PATCH] Add ability to ignore signals --- README.md | 2 ++ dumb-init.c | 18 ++++++++++++------ tests/cli_test.py | 2 ++ tests/proxies_signals_test.py | 18 ++++++++++++++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index c38850e..e04d449 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,8 @@ different stop signal in order to do graceful cleanup. For example, to rewrite the signal SIGTERM (number 15) to SIGQUIT (number 3), just add `--rewrite 15:3` on the command line. +To drop a signal entirely, you can rewrite it to the special number `0`. + #### Signal rewriting special case diff --git a/dumb-init.c b/dumb-init.c index f0069e7..af4f92d 100644 --- a/dumb-init.c +++ b/dumb-init.c @@ -35,7 +35,7 @@ #define MAXSIG 31 // Indices are one-indexed (signal 1 is at index 1). Index zero is unused. -int signal_rewrite[MAXSIG + 1] = {0}; +int signal_rewrite[MAXSIG + 1] = {[0 ... MAXSIG] = -1}; pid_t child_pid = -1; char debug = 0; @@ -46,14 +46,18 @@ int translate_signal(int signum) { return signum; } else { int translated = signal_rewrite[signum]; - return translated == 0 ? signum : translated; + return translated == -1 ? signum : translated; } } void forward_signal(int signum) { signum = translate_signal(signum); - kill(use_setsid ? -child_pid : child_pid, signum); - DEBUG("Forwarded signal %d to children.\n", signum); + if (signum != -1) { + kill(use_setsid ? -child_pid : child_pid, signum); + DEBUG("Forwarded signal %d to children.\n", signum); + } else { + DEBUG("Not forwarding signal %d to children (ignored).\n", signum); + } } /* @@ -119,6 +123,8 @@ void print_help(char *argv[]) { " In this mode, signals are only proxied to the\n" " direct child and not any of its descendants.\n" " -r, --rewrite s:r Rewrite received signal s to new signal r before proxying.\n" + " To ignore (not proxy) a signal, rewrite it to 0.\n" + " This option can be specified multiple times.\n" " -v, --verbose Print debugging information to stderr.\n" " -h, --help Print this help message and exit.\n" " -V, --version Print the current version and exit.\n" @@ -146,7 +152,7 @@ void parse_rewrite_signum(char *arg) { if ( sscanf(arg, "%d:%d", &signum, &replacement) == 2 && (signum >= 1 && signum <= MAXSIG) && - (replacement >= 1 && replacement <= MAXSIG) + (replacement >= 0 && replacement <= MAXSIG) ) { signal_rewrite[signum] = replacement; } else { @@ -155,7 +161,7 @@ void parse_rewrite_signum(char *arg) { } void set_rewrite_to_sigstop_if_not_defined(int signum) { - if (signal_rewrite[signum] == 0) + if (signal_rewrite[signum] == -1) signal_rewrite[signum] = SIGSTOP; } diff --git a/tests/cli_test.py b/tests/cli_test.py index 1bc7a19..1fe4584 100644 --- a/tests/cli_test.py +++ b/tests/cli_test.py @@ -41,6 +41,8 @@ def test_help_message(flag, both_debug_modes, both_setsid_modes, current_version b' In this mode, signals are only proxied to the\n' b' direct child and not any of its descendants.\n' b' -r, --rewrite s:r Rewrite received signal s to new signal r before proxying.\n' + b' To ignore (not proxy) a signal, rewrite it to 0.\n' + b' This option can be specified multiple times.\n' b' -v, --verbose Print debugging information to stderr.\n' b' -h, --help Print this help message and exit.\n' b' -V, --version Print the current version and exit.\n' diff --git a/tests/proxies_signals_test.py b/tests/proxies_signals_test.py index 79c691b..d9d0657 100644 --- a/tests/proxies_signals_test.py +++ b/tests/proxies_signals_test.py @@ -109,3 +109,21 @@ def test_default_rewrites_can_be_overriden_with_setsid_enabled(): proc.send_signal(signal.SIGCONT) assert proc.stdout.readline() == '{0}\n'.format(signal.SIGCONT).encode('ascii') assert process_state(proc.pid) in ['running', 'sleeping'] + + +@pytest.mark.usefixtures('both_debug_modes', 'both_setsid_modes') +def test_ignored_signals_are_not_proxied(): + """Ensure dumb-init can ignore signals.""" + rewrite_map = { + signal.SIGTERM: signal.SIGQUIT, + signal.SIGINT: 0, + signal.SIGWINCH: 0, + } + with _print_signals(_rewrite_map_to_args(rewrite_map)) as proc: + proc.send_signal(signal.SIGTERM) + proc.send_signal(signal.SIGINT) + assert proc.stdout.readline() == '{0}\n'.format(signal.SIGQUIT).encode('ascii') + + proc.send_signal(signal.SIGWINCH) + proc.send_signal(signal.SIGHUP) + assert proc.stdout.readline() == '{0}\n'.format(signal.SIGHUP).encode('ascii')