add a -w option to warn on reaping children

Well designed software should not produce any zombie or re-parenting
processes.

This adds an option to warn in the logs when reaping of zombies is
happening so that it can be monitored and fixed in subsequent releases
of the software.
pull/107/head
zimbatm 7 years ago committed by Thomas Orozco
parent 0effd37412
commit 8574e10c2a
  1. 2
      ci/run_build.sh
  2. 13
      src/tini.c
  3. 14
      test/run_inner_tests.py
  4. 1
      test/run_outer_tests.py

@ -105,7 +105,7 @@ if [[ -n "${ARCH_NATIVE-}" ]]; then
# We try running binaries named after flags (both valid and invalid
# flags) and test that they run.
for flag in h s x; do
for flag in h s w x; do
bin="-${flag}"
echo "Testing $tini can run binary: ${bin}"
cp "$(which true)" "${BIN_TEST_DIR}/${bin}"

@ -45,11 +45,11 @@ static unsigned int verbosity = DEFAULT_VERBOSITY;
#ifdef PR_SET_CHILD_SUBREAPER
#define HAS_SUBREAPER 1
#define OPT_STRING "hsvgl"
#define OPT_STRING "hsvwgl"
#define SUBREAPER_ENV_VAR "TINI_SUBREAPER"
#else
#define HAS_SUBREAPER 0
#define OPT_STRING "hvgl"
#define OPT_STRING "hvwgl"
#endif
#define VERBOSITY_ENV_VAR "TINI_VERBOSITY"
@ -62,6 +62,8 @@ static unsigned int subreaper = 0;
#endif
static unsigned int kill_process_group = 0;
static unsigned int warn_on_reap = 0;
static struct timespec ts = { .tv_sec = 1, .tv_nsec = 0 };
static const char reaper_warning[] = "Tini is not running as PID 1 "
@ -195,6 +197,7 @@ void print_usage(char* const name, FILE* const file) {
fprintf(file, " -s: Register as a process subreaper (requires Linux >= 3.4).\n");
#endif
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");
fprintf(file, " -l: Show license and exit.\n");
#endif
@ -247,6 +250,10 @@ int parse_args(const int argc, char* const argv[], char* (**child_args_ptr_ptr)[
verbosity++;
break;
case 'w':
warn_on_reap++;
break;
case 'g':
kill_process_group++;
break;
@ -470,6 +477,8 @@ int reap_zombies(const pid_t child_pid, int* const child_exitcode_ptr) {
PRINT_FATAL("Main child exited for unknown reason");
return 1;
}
} else if (warn_on_reap > 0) {
PRINT_WARNING("Reaped zombie process with pid=%i", current_pid);
}
// Check if other childs have been reaped.

@ -57,9 +57,22 @@ def main():
# and will output the error message here.
assert "zombie reaping won't work" not in err, "Warning message was output!"
ret = p.wait()
assert "Reaped zombie process with pid=" not in err, "Warning message was output!"
assert ret == 0, "Reaping test failed!\nOUT: %s\nERR: %s" % (out, err)
if not args_disabled:
print "Running reaping display test ({0} with env {1})".format(" ".join(target), env)
p = subprocess.Popen(target + ["-w", os.path.join(src, "test", "reaping", "stage_1.py")],
env=dict(os.environ, **env),
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
ret = p.wait()
assert "Reaped zombie process with pid=" in err, "Warning message was output!"
assert ret == 0, "Reaping display test failed!\nOUT: %s\nERR: %s" % (out, err)
# Run the signals test
for signum in [signal.SIGTERM, signal.SIGUSR1, signal.SIGUSR2]:
print "running signal test for: {0} ({1} with env {2})".format(signum, " ".join(target), env)
@ -94,7 +107,6 @@ def main():
ret = p.wait()
assert ret == 1, "Reaping test succeeded (it should have failed)!"
# Test that the signals are properly in place here.
print "running signal configuration test"

@ -158,6 +158,7 @@ def main():
Command(functional_base_cmd + ["-z"], fail_cmd).run(retcode=127 if args_disabled else 1)
Command(functional_base_cmd + ["-h"], fail_cmd).run(retcode=127 if args_disabled else 0)
Command(functional_base_cmd + ["zzzz"], fail_cmd).run(retcode=127)
Command(functional_base_cmd + ["-w"], fail_cmd).run(retcode=127 if args_disabled else 0)
# Valgrind test (we only run this on the dynamic version, because otherwise Valgrind may bring up plenty of errors that are
# actually from libc)

Loading…
Cancel
Save