Created
September 8, 2017 20:23
-
-
Save groner/7d887c400749a4c82303773bf2dddcb5 to your computer and use it in GitHub Desktop.
wrapper script to run a command with a timeout
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use POSIX qw(WNOHANG WIFEXITED WEXITSTATUS WIFSIGNALED WTERMSIG); | |
use Time::HiRes qw(gettimeofday); | |
die "usage: $0 TIMEOUT COMMAND ...\n" if (@ARGV < 2); | |
$timeout = shift @ARGV; | |
$pid = fork(); | |
die "fork: $!" if not defined $pid; | |
if ($pid == 0) { | |
exec @ARGV or die "$ARGV[0]: $!"; | |
} | |
$SIG{"CHLD"} = sub { | |
waitpid $pid, WNOHANG; | |
exit WEXITSTATUS($?) if WIFEXITED($?); | |
if (WIFSIGNALED($?)) { | |
kill WTERMSIG($?), $$; | |
# Still here? Signal was handled, so just report it and exit. | |
die "Signal ${WTERMSIG($?)}"; | |
} | |
}; | |
$endtime = gettimeofday()+$timeout; | |
sleep($endtime-gettimeofday()) while (gettimeofday() < $endtime); | |
print STDERR "timeout!\n"; | |
kill "TERM", $pid; | |
while (1) { sleep(1) } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Could use a second timeout with a hard kill.
Doesn't try to relay signals. It could run in the background, and poll. Polling is ugly, and it could mistarget the wrong process when pids are recycled.