NS.timeout,
)
+def do_exec(NS):
+ cargs = NS.cmd + NS.args
+ popen_kwargs = {
+ "stdin": subprocess.PIPE,
+ }
-if __name__ == "__main__":
+ if NS.setpgrp == "self":
+ pgrp = os.getpgrp()
+ if pgrp != os.getpid():
+ os.setpgrp()
+ pgrp = os.getpgrp()
+ elif NS.setpgrp == "child":
+ popen_kwargs["preexec_fn"] = os.setpgrp
+ pgrp = None
+ elif NS.setpgrp == "no":
+ pgrp = 0
+ else:
+ assert False
+
+ log.debug("executing %s", cargs)
+ p = subprocess.Popen(cargs, **popen_kwargs)
+ if pgrp is None:
+ pgrp = p.pid
+ flags = fcntl.fcntl(p.stdin.fileno(), fcntl.F_GETFL)
+ fcntl.fcntl(p.stdin.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
+
+ listen_for_events(sigfdr, p, NS.timeout)
+
+ if p.returncode is None:
+ log.error("timeout expired: sending signal %d to command and myself", NS.signal)
+ if pgrp == 0:
+ os.kill(p.pid, NS.signal)
+ else:
+ os.killpg(pgrp, NS.signal) # should kill me too
+ os.kill(os.getpid(), NS.signal) # to exit abnormally with same signal
+ log.error("signal did not cause termination, sending myself SIGKILL")
+ os.kill(os.getpid(), signal.SIGKILL) # failsafe
+ rc = p.returncode
+ log.debug("rc = %d", rc)
+ assert rc is not None
+ if rc < 0:
+ log.error("command terminated with signal %d: sending same signal to myself!", -rc)
+ os.kill(os.getpid(), -rc) # kill myself with the same signal
+ log.error("signal did not cause termination, sending myself SIGKILL")
+ os.kill(os.getpid(), signal.SIGKILL) # failsafe
+ else:
+ log.info("command exited with status %d: exiting normally with same code!", rc)
+ return rc
+
+
+def main():
signal.signal(signal.SIGPIPE, signal.SIG_IGN)
try:
(sigfdr, sigfdw) = os.pipe2(os.O_NONBLOCK | os.O_CLOEXEC)
default=signal.SIGKILL,
)
P.add_argument("--verbose", action="store_true", help="increase debugging")
+ P.add_argument("--reboot-on-exit0", dest='reboot', action="store_true", help="reboot command on exit 0")
P.add_argument(
"--setpgrp",
action="store",
logargs["datefmt"] = "%Y-%m-%dT%H:%M:%S"
logging.basicConfig(**logargs)
- cargs = NS.cmd + NS.args
- popen_kwargs = {
- "stdin": subprocess.PIPE,
- }
-
- if NS.setpgrp == "self":
- pgrp = os.getpgrp()
- if pgrp != os.getpid():
- os.setpgrp()
- pgrp = os.getpgrp()
- elif NS.setpgrp == "child":
- popen_kwargs["preexec_fn"] = os.setpgrp
- pgrp = None
- elif NS.setpgrp == "no":
- pgrp = 0
- else:
- assert False
-
- log.debug("executing %s", cargs)
- p = subprocess.Popen(cargs, **popen_kwargs)
- if pgrp is None:
- pgrp = p.pid
- flags = fcntl.fcntl(p.stdin.fileno(), fcntl.F_GETFL)
- fcntl.fcntl(p.stdin.fileno(), fcntl.F_SETFL, flags | os.O_NONBLOCK)
-
- listen_for_events(sigfdr, p, NS.timeout)
+ while True:
+ rc = do_exec(NS)
+ if rc != 0 or not NS.reboot:
+ sys.exit(rc)
- if p.returncode is None:
- log.error("timeout expired: sending signal %d to command and myself", NS.signal)
- if pgrp == 0:
- os.kill(p.pid, NS.signal)
- else:
- os.killpg(pgrp, NS.signal) # should kill me too
- os.kill(os.getpid(), NS.signal) # to exit abnormally with same signal
- log.error("signal did not cause termination, sending myself SIGKILL")
- os.kill(os.getpid(), signal.SIGKILL) # failsafe
- rc = p.returncode
- log.debug("rc = %d", rc)
- assert rc is not None
- if rc < 0:
- log.error("command terminated with signal %d: sending same signal to myself!", -rc)
- os.kill(os.getpid(), -rc) # kill myself with the same signal
- log.error("signal did not cause termination, sending myself SIGKILL")
- os.kill(os.getpid(), signal.SIGKILL) # failsafe
- else:
- log.info("command exited with status %d: exiting normally with same code!", rc)
- sys.exit(rc)
+if __name__ == "__main__":
+ main()