I have a an external program prog
, and I am writing a julia program that prepares various data sets and measures the run time of prog
for each of the data sets. My question is about how to run prog
. Of course, I am aware of run
. However, I also want to satisfy the following demands:
prog
should be aborted if a run exceeds N seconds- ideally, all running instances of
prog
should be aborted if I hit ^C in the REPL, - ideally, I measure not elapsed time, but cpu time of prog.
Therefore, I came up with this snippet. I refrained from using@elapsed
, because I want to be closer to the actual cpu time of the process:
function test_runtime(timeout=Inf)
time_path = tempname()
process = run(pipeline(`/usr/bin/time -f%U -o$time_path sleep 10000`; stdout=devnull), wait=false)
future = @async begin
wait(process)
return open(io->tryparse(Float64, readline(io)), time_path)
end
try
if timedwait(()->istaskdone(future), timeout; pollint=1) == :timed_out
println("timeout; send sigint to process.")
kill(process, Base.SIGINT)
end
return fetch(future)
catch e
if isa(e, InterruptException)
println("Interrupted; send interrupt to process.")
kill(process, Base.SIGINT)
else
rethrow(e)
end
end
end
my concerns are:
- the detour via
time
with the temporary file for the output is rather clumsy. Ideally, I would have a builtin access to the stats of the subprocess, but this seems impossible. - The subprocess (time and its child) are not properly killed. This seems to be no julia problem, but a problem that
time
ignores sigint. Sending sigterm would be an option, but this won’t kill the actual child oftime
. - if I use
@elapsed
instead oftime
, killing the subprocess works, but I’d prefer having access to the cpu time instead of wall time.