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:
progshould be aborted if a run exceeds N seconds- ideally, all running instances of
progshould 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
timewith 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
timeignores sigint. Sending sigterm would be an option, but this won’t kill the actual child oftime. - if I use
@elapsedinstead oftime, killing the subprocess works, but I’d prefer having access to the cpu time instead of wall time.