8000 Add '-p' flag to get signalled when parent dies by pks-t · Pull Request #114 · krallin/tini · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Add '-p' flag to get signalled when parent dies #114

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 21, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
10000
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
5D39
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