Skip to content

Commit

Permalink
Merge pull request #114 from pks-t/pks/pdeathsignal
Browse files Browse the repository at this point in the history
Add '-p' flag to get signalled  when parent dies
  • Loading branch information
krallin authored Apr 21, 2018
2 parents 5b117de + a500ee7 commit e972ea5
Show file tree
Hide file tree
Showing 6 changed files with 172 additions and 3 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,20 @@ closely to what happens when you do ctrl-C etc. in a terminal: The
signal is sent to the foreground process group.


### Parent Death Signal ###

Tini can set its parent death signal, which is the signal Tini should receive
when *its* parent exits. To set the parent death signal, use the `-p` flag with
the name of the signal Tini should receive when its parent exits:

```
tini -p SIGTERM -- ...
```

*NOTE: See [this PR discussion][12] to learn more about the parent death signal
and use cases.*


More
----

Expand Down Expand Up @@ -257,6 +271,7 @@ Contributors:
+ [David Wragg][31]
+ [Michael Crosby][32]
+ [Wyatt Preul][33]
+ [Patrick Steinhardt][34]

Special thanks to:

Expand All @@ -268,10 +283,12 @@ Special thanks to:
[5]: https://docs.docker.com/engine/reference/commandline/run/
[10]: https://github.com/krallin/tini-images
[11]: https://github.com/krallin/tini/releases
[12]: https://github.com/krallin/tini/pull/114
[20]: https://github.com/krallin/
[30]: https://github.com/tianon
[31]: https://github.com/dpw
[32]: https://github.com/crosbymichael
[33]: https://github.com/geek
[34]: https://github.com/pks-t
[40]: https://github.com/danilobuerger
[41]: https://github.com/datakurre
68 changes: 66 additions & 2 deletions src/tini.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,51 @@ typedef struct {
struct sigaction* const sigttou_action_ptr;
} signal_configuration_t;

static const struct {
char *const name;
int number;
} signal_names[] = {
{ "SIGHUP", SIGHUP },
{ "SIGINT", SIGINT },
{ "SIGQUIT", SIGQUIT },
{ "SIGILL", SIGILL },
{ "SIGTRAP", SIGTRAP },
{ "SIGABRT", SIGABRT },
{ "SIGBUS", SIGBUS },
{ "SIGFPE", SIGFPE },
{ "SIGKILL", SIGKILL },
{ "SIGUSR1", SIGUSR1 },
{ "SIGSEGV", SIGSEGV },
{ "SIGUSR2", SIGUSR2 },
{ "SIGPIPE", SIGPIPE },
{ "SIGALRM", SIGALRM },
{ "SIGTERM", SIGTERM },
{ "SIGCHLD", SIGCHLD },
{ "SIGCONT", SIGCONT },
{ "SIGSTOP", SIGSTOP },
{ "SIGTSTP", SIGTSTP },
{ "SIGTTIN", SIGTTIN },
{ "SIGTTOU", SIGTTOU },
{ "SIGURG", SIGURG },
{ "SIGXCPU", SIGXCPU },
{ "SIGXFSZ", SIGXFSZ },
{ "SIGVTALRM", SIGVTALRM },
{ "SIGPROF", SIGPROF },
{ "SIGWINCH", SIGWINCH },
{ "SIGSYS", SIGSYS },
};

static unsigned int verbosity = DEFAULT_VERBOSITY;

static int32_t expect_status[(STATUS_MAX - STATUS_MIN + 1) / 32];

#ifdef PR_SET_CHILD_SUBREAPER
#define HAS_SUBREAPER 1
#define OPT_STRING "hvwgle:s"
#define OPT_STRING "p:hvwgle:s"
#define SUBREAPER_ENV_VAR "TINI_SUBREAPER"
#else
#define HAS_SUBREAPER 0
#define OPT_STRING "hvwgle:"
#define OPT_STRING "p:hvwgle:"
#endif

#define VERBOSITY_ENV_VAR "TINI_VERBOSITY"
Expand All @@ -71,6 +105,7 @@ static int32_t expect_status[(STATUS_MAX - STATUS_MIN + 1) / 32];
#if HAS_SUBREAPER
static unsigned int subreaper = 0;
#endif
static unsigned int parent_death_signal = 0;
static unsigned int kill_process_group = 0;

static unsigned int warn_on_reap = 0;
Expand Down Expand Up @@ -207,6 +242,7 @@ void print_usage(char* const name, FILE* const file) {
#if HAS_SUBREAPER
fprintf(file, " -s: Register as a process subreaper (requires Linux >= 3.4).\n");
#endif
fprintf(file, " -p SIGNAL: Trigger SIGNAL when parent dies, e.g. \"-p SIGKILL\".\n");
fprintf(file, " -v: Generate more verbose output. Repeat up to 3 times.\n");
fprintf(file, " -w: Print a warning when processes are getting reaped.\n");
fprintf(file, " -g: Send signals to the child's process group.\n");
Expand Down Expand Up @@ -235,6 +271,20 @@ void print_license(FILE* const file) {
}
}

int set_pdeathsig(char* const arg) {
size_t i;

for (i = 0; i < ARRAY_LEN(signal_names); i++) {
if (strcmp(signal_names[i].name, arg) == 0) {
/* Signals start at value "1" */
parent_death_signal = signal_names[i].number;
return 0;
}
}

return 1;
}

int add_expect_status(char* arg) {
long status = 0;
char* endptr = NULL;
Expand Down Expand Up @@ -276,6 +326,14 @@ int parse_args(const int argc, char* const argv[], char* (**child_args_ptr_ptr)[
subreaper++;
break;
#endif
case 'p':
if (set_pdeathsig(optarg)) {
PRINT_FATAL("Not a valid option for -p: %s", optarg);
*parse_fail_exitcode_ptr = 1;
return 1;
}
break;

case 'v':
verbosity++;
break;
Expand Down Expand Up @@ -575,6 +633,12 @@ int main(int argc, char *argv[]) {
return 1;
}

/* Trigger signal on this process when the parent process exits. */
if (parent_death_signal && prctl(PR_SET_PDEATHSIG, parent_death_signal)) {
PRINT_FATAL("Failed to set up parent death signal");
return 1;
}

#if HAS_SUBREAPER
/* If available and requested, register as a subreaper */
if (register_subreaper()) {
Expand Down
30 changes: 30 additions & 0 deletions test/pdeathsignal/stage_1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env python
from __future__ import print_function

import os
import sys
import subprocess


def main():
pid = os.getpid()

tini = sys.argv[1]
ret = sys.argv[2]
stage_2 = os.path.join(os.path.dirname(__file__), "stage_2.py")

cmd = [
tini,
"-vvv",
"-p",
"SIGUSR1",
"--",
stage_2,
str(pid),
ret
]

subprocess.Popen(cmd).wait()

if __name__ == "__main__":
main()
25 changes: 25 additions & 0 deletions test/pdeathsignal/stage_2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env python
from __future__ import print_function

import os
import sys
import signal
import time


def main():
ret = sys.argv[2]

def handler(*args):
with open(ret, "w") as f:
f.write("ok")
sys.exit(0)

signal.signal(signal.SIGUSR1, handler)
pid = int(sys.argv[1])

os.kill(pid, signal.SIGKILL)
time.sleep(5)

if __name__ == "__main__":
main()
18 changes: 17 additions & 1 deletion test/run_inner_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import bitmap
import re
import itertools
import tempfile

DEVNULL = open(os.devnull, 'wb')

Expand Down Expand Up @@ -133,7 +134,7 @@ def main():
assert ret == 1, "Reaping test succeeded (it should have failed)!"

# Test that the signals are properly in place here.
print "running signal configuration test"
print "Running signal configuration test"

p = subprocess.Popen([os.path.join(build, "sigconf-test"), tini, "cat", "/proc/self/status"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
Expand All @@ -156,6 +157,21 @@ def main():
# Use signum - 1 because the bitmap is 0-indexed but represents signals strting at 1
assert (signum - 1) in props[signal_set_name].nonzero(), "{0} ({1}) is missing in {2}!".format(SIGNUM_TO_SIGNAME[signum], signum, signal_set_name)

# Test parent death signal handling.
if not args_disabled:
print "Running parent death signal test"
f = tempfile.NamedTemporaryFile()
try:
p = subprocess.Popen(
[os.path.join(src, "test", "pdeathsignal", "stage_1.py"), tini, f.name],
stdout=DEVNULL, stderr=DEVNULL
)
p.wait()

busy_wait(lambda: open(f.name).read() == "ok", 10)
finally:
f.close()

print "---------------------------"
print "All done, tests as expected"
print "---------------------------"
Expand Down
17 changes: 17 additions & 0 deletions tpl/README.md.in
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,20 @@ closely to what happens when you do ctrl-C etc. in a terminal: The
signal is sent to the foreground process group.


### Parent Death Signal ###

Tini can set its parent death signal, which is the signal Tini should receive
when *its* parent exits. To set the parent death signal, use the `-p` flag with
the name of the signal Tini should receive when its parent exits:

```
tini -p SIGTERM -- ...
```

*NOTE: See [this PR discussion][12] to learn more about the parent death signal
and use cases.*


More
----

Expand Down Expand Up @@ -257,6 +271,7 @@ Contributors:
+ [David Wragg][31]
+ [Michael Crosby][32]
+ [Wyatt Preul][33]
+ [Patrick Steinhardt][34]

Special thanks to:

Expand All @@ -268,10 +283,12 @@ Special thanks to:
[5]: https://docs.docker.com/engine/reference/commandline/run/
[10]: https://github.com/krallin/tini-images
[11]: https://github.com/krallin/tini/releases
[12]: https://github.com/krallin/tini/pull/114
[20]: https://github.com/krallin/
[30]: https://github.com/tianon
[31]: https://github.com/dpw
[32]: https://github.com/crosbymichael
[33]: https://github.com/geek
[34]: https://github.com/pks-t
[40]: https://github.com/danilobuerger
[41]: https://github.com/datakurre

0 comments on commit e972ea5

Please sign in to comment.