8335076173
Initial mockup for a tool which restarts its subprocess on SIGHUP, and stops everything on SIGTERM and SIGINT. Change-Id: Ie5260d73c2663d1821eb6623e2bc61d16f6c92cd Reviewed-on: https://cl.tvl.fyi/c/depot/+/11168 Autosubmit: Profpatsch <mail@profpatsch.de> Reviewed-by: Profpatsch <mail@profpatsch.de> Tested-by: BuildkiteCI
172 lines
3.6 KiB
Nix
172 lines
3.6 KiB
Nix
{ depot, lib, pkgs, ... }:
|
||
|
||
let
|
||
# run prog... and restart whenever SIGHUP is received
|
||
#
|
||
# this is useful for binding to a shortcut.
|
||
#
|
||
# Unfortunately, this requires a bunch of workarounds around the semantics of `trap`,
|
||
# but the general idea of bundling subprocesses with `setsid` is somewhat sound.
|
||
runShortcuttable =
|
||
depot.nix.writeExecline "run-shortcuttable" { } [
|
||
"importas"
|
||
"-i"
|
||
"run"
|
||
"XDG_RUNTIME_DIR"
|
||
"if"
|
||
[ "mkdir" "-p" "\${run}/shortcuttable/test" ]
|
||
"getpid"
|
||
"-E"
|
||
"controlpid"
|
||
savePid
|
||
"\${run}/shortcuttable/test/control"
|
||
"$controlpid"
|
||
|
||
# start the program
|
||
"background"
|
||
[
|
||
startSaveSID
|
||
"\${run}/shortcuttable/test/running-sid"
|
||
"$@"
|
||
]
|
||
|
||
"trap"
|
||
[
|
||
"SIGHUP"
|
||
[
|
||
"if"
|
||
[ "echo" "got hup" ]
|
||
"if"
|
||
[
|
||
"if"
|
||
[ "echo" "killing our child processes" ]
|
||
"envfile"
|
||
"\${run}/shortcuttable/test/running-sid"
|
||
"importas"
|
||
"-ui"
|
||
"child_sid"
|
||
"pid"
|
||
"foreground"
|
||
[ "ps" "-f" "--sid" "$child_sid" ]
|
||
ctrlCCtrlDSid
|
||
"$child_sid"
|
||
]
|
||
"if"
|
||
[ "echo" "restarting into" "$@" ]
|
||
"background"
|
||
[
|
||
startSaveSID
|
||
"\${run}/shortcuttable/test/running-sid"
|
||
"$@"
|
||
]
|
||
]
|
||
"SIGTERM"
|
||
[
|
||
(killShortcuttable { signal = "TERM"; })
|
||
"\${run}/shortcuttable/test/running-sid"
|
||
"\${run}/shortcuttable/test/exit"
|
||
]
|
||
"SIGINT"
|
||
[
|
||
(killShortcuttable { signal = "INT"; })
|
||
"\${run}/shortcuttable/test/running-sid"
|
||
"\${run}/shortcuttable/test/exit"
|
||
]
|
||
]
|
||
depot.users.Profpatsch.execline.setsid
|
||
"child_sid"
|
||
"getpid"
|
||
"-E"
|
||
"exitpid"
|
||
savePid
|
||
"\${run}/shortcuttable/test/exit"
|
||
"$exitpid"
|
||
"sleep"
|
||
"infinity"
|
||
];
|
||
|
||
killShortcuttable = { signal }: depot.nix.writeExecline "kill-shortcuttable" { readNArgs = 2; } [
|
||
"if"
|
||
[ "echo" "got SIG${signal}, quitting" ]
|
||
"if"
|
||
[
|
||
"envfile"
|
||
"$1"
|
||
"importas"
|
||
"-ui"
|
||
"child_sid"
|
||
"pid"
|
||
"foreground"
|
||
[ "ps" "-f" "--sid" "$child_sid" ]
|
||
ctrlCCtrlDSid
|
||
"$child_sid"
|
||
]
|
||
"if"
|
||
[ "echo" "killing shortcuttable loop" ]
|
||
"envfile"
|
||
"$2"
|
||
"importas"
|
||
"-ui"
|
||
"trap_pid"
|
||
"pid"
|
||
"foreground"
|
||
[ "ps" "-fp" "$trap_pid" ]
|
||
"kill"
|
||
"--signal"
|
||
signal
|
||
"$trap_pid"
|
||
];
|
||
|
||
savePid = depot.nix.writeExecline "save-pid" { readNArgs = 2; } [
|
||
"if"
|
||
[ "echo" "saving process:" ]
|
||
"if"
|
||
[ "ps" "-fp" "$2" ]
|
||
"if"
|
||
[
|
||
"redirfd"
|
||
"-w"
|
||
"1"
|
||
"$1"
|
||
"printf"
|
||
"pid = %s\n"
|
||
"$2"
|
||
]
|
||
"$@"
|
||
];
|
||
|
||
# try to kill process, first with SIGTERM then SIGQUIT (in case it’s a repl)
|
||
ctrlCCtrlDSid = depot.nix.writeExecline "ctrl-c-ctrl-d" { readNArgs = 1; } [
|
||
"ifelse"
|
||
"-n"
|
||
[ "kill" "--signal" "TERM" "--" "-\${1}" ]
|
||
[
|
||
"if"
|
||
[ "echo" "could not kill via SIGTERM, trying SIGQUIT …" ]
|
||
"ifelse"
|
||
"-n"
|
||
[ "kill" "--signal" "QUIT" "--" "-\${1}" ]
|
||
[ "echo" "SIGQUIT failed as well, keeping it running" ]
|
||
"$@"
|
||
]
|
||
"$@"
|
||
];
|
||
|
||
startSaveSID = depot.nix.writeExecline "start-save-sid" { readNArgs = 1; } [
|
||
depot.users.Profpatsch.execline.setsid
|
||
"child_sid"
|
||
"importas"
|
||
"-ui"
|
||
"child_sid"
|
||
"child_sid"
|
||
"if"
|
||
[ "echo" "children sid:" "$child_sid" ]
|
||
savePid
|
||
"$1"
|
||
"$child_sid"
|
||
"$@"
|
||
];
|
||
|
||
|
||
in
|
||
runShortcuttable
|