diff options
Diffstat (limited to 'tests/integration/pdeathsig.py')
| -rwxr-xr-x | tests/integration/pdeathsig.py | 44 |
1 files changed, 44 insertions, 0 deletions
diff --git a/tests/integration/pdeathsig.py b/tests/integration/pdeathsig.py new file mode 100755 index 00000000..d4a25ac7 --- /dev/null +++ b/tests/integration/pdeathsig.py @@ -0,0 +1,44 @@ +#!/usr/bin/env python3 +"""Exec a command with PR_SET_PDEATHSIG — receive a signal when parent dies. + +Usage: pdeathsig.py SIGNAL COMMAND [ARGS...] + +Fallback for systems without `setpriv --pdeathsig`. +""" +import ctypes +import ctypes.util +import os +import signal +import sys + +PR_SET_PDEATHSIG = 1 + +SIGNALS = { + "TERM": signal.SIGTERM, "SIGTERM": signal.SIGTERM, + "INT": signal.SIGINT, "SIGINT": signal.SIGINT, + "HUP": signal.SIGHUP, "SIGHUP": signal.SIGHUP, + "KILL": signal.SIGKILL, "SIGKILL": signal.SIGKILL, +} + +def main() -> int: + if len(sys.argv) < 3: + print(f"usage: {sys.argv[0]} SIGNAL COMMAND [ARGS...]", file=sys.stderr) + return 2 + sig_name = sys.argv[1] + argv = sys.argv[2:] + if sig_name not in SIGNALS: + print(f"unknown signal: {sig_name}", file=sys.stderr) + return 2 + sig = SIGNALS[sig_name] + libc = ctypes.CDLL(ctypes.util.find_library("c") or "libc.so.6", use_errno=True) + if libc.prctl(PR_SET_PDEATHSIG, sig, 0, 0, 0) != 0: + err = ctypes.get_errno() + raise OSError(err, os.strerror(err)) + # Race fix: parent may have died before prctl took effect + if os.getppid() == 1: + os.kill(os.getpid(), sig) + os.execvp(argv[0], argv) + return 127 + +if __name__ == "__main__": + raise SystemExit(main()) |
