Measuring stats (cpu time etc.) for external program

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 of time.
  • if I use @elapsed instead of time, killing the subprocess works, but I’d prefer having access to the cpu time instead of wall time.