diff --git a/src/tini.c b/src/tini.c index 3753867..3ad8232 100644 --- a/src/tini.c +++ b/src/tini.c @@ -98,6 +98,7 @@ static int32_t expect_status[(STATUS_MAX - STATUS_MIN + 1) / 32]; #endif #define VERBOSITY_ENV_VAR "TINI_VERBOSITY" +#define KILL_PROCESS_GROUP_GROUP_ENV_VAR "TINI_KILL_PROCESS_GROUP" #define TINI_VERSION_STRING "tini version " TINI_VERSION TINI_GIT @@ -254,9 +255,10 @@ void print_usage(char* const name, FILE* const file) { fprintf(file, "Environment variables:\n\n"); #if HAS_SUBREAPER - fprintf(file, " %s: Register as a process subreaper (requires Linux >= 3.4)\n", SUBREAPER_ENV_VAR); + fprintf(file, " %s: Register as a process subreaper (requires Linux >= 3.4).\n", SUBREAPER_ENV_VAR); #endif - fprintf(file, " %s: Set the verbosity level (default: %d)\n", VERBOSITY_ENV_VAR, DEFAULT_VERBOSITY); + fprintf(file, " %s: Set the verbosity level (default: %d).\n", VERBOSITY_ENV_VAR, DEFAULT_VERBOSITY); + fprintf(file, " %s: Send signals to the child's process group.\n", KILL_PROCESS_GROUP_GROUP_ENV_VAR); fprintf(file, "\n"); } @@ -397,6 +399,10 @@ int parse_env() { } #endif + if (getenv(KILL_PROCESS_GROUP_GROUP_ENV_VAR) != NULL) { + kill_process_group++; + } + char* env_verbosity = getenv(VERBOSITY_ENV_VAR); if (env_verbosity != NULL) { verbosity = atoi(env_verbosity); diff --git a/test/run_inner_tests.py b/test/run_inner_tests.py index 4468797..e060e18 100755 --- a/test/run_inner_tests.py +++ b/test/run_inner_tests.py @@ -113,13 +113,24 @@ def main(): # This test has Tini spawn a process that ignores SIGUSR1 and spawns a child that doesn't (and waits on the child) # We send SIGUSR1 to Tini, and expect the grand-child to terminate, then the child, and then Tini. if not args_disabled: - print "Running process group test" + print "Running process group test (arguments)" p = subprocess.Popen([tini, '-g', os.path.join(src, "test", "pgroup", "stage_1.py")], stdout=subprocess.PIPE, stderr=subprocess.PIPE) busy_wait(lambda: len(psutil.Process(p.pid).children(recursive=True)) == 2, 10) p.send_signal(signal.SIGUSR1) busy_wait(lambda: p.poll() is not None, 10) + print "Running process group test (environment variable)" + p = subprocess.Popen( + [tini, os.path.join(src, "test", "pgroup", "stage_1.py")], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, + env=dict(os.environ, TINI_KILL_PROCESS_GROUP="1") + ) + + busy_wait(lambda: len(psutil.Process(p.pid).children(recursive=True)) == 2, 10) + p.send_signal(signal.SIGUSR1) + busy_wait(lambda: p.poll() is not None, 10) + # Run failing test. Force verbosity to 1 so we see the subreaper warning # regardless of whether MINIMAL is set. print "Running zombie reaping failure test (Tini should warn)"