def do_work
process = Process.new ("D:/tool.bat", ["-version"])
p process.pid
process.wait
end
spawn do
loop do
do_work
end
end
spawn do
loop do
do_work
end
end
sleep
I want to use the process class to run an external tool. What would be a reasonable solution to implement a timeout which terminates the process after the specified time ?
Use channel and select with timeout. Something like
def do_work
channel = Channel(Process::Status).new(capacity: 1)
process = nil
spawn do
process = Process.new ("D:/tool.bat", ["-version"])
status = process.wait
channel.send(status) unless channel.closed?
end
select
when status = channel.receive
# process terminates before timeout
# .....
when timeout(MY_TIMEOUT) # MY_TIMEOUT is your own custom timeout value you want to wait
# this will be reached when `timeout` is met and process still running
channel.close
process.try &.terminate rescue nil
# process.terminate may raise, so better to catch and handle. above example just ignoring the exception
end
end
While digging in the crystal sources I found in ‘spec/std/thread_spec.cr’ a hint:
it "returns current thread object" do
current = nil
thread = Thread.new { current = Thread.current }
thread.join
current.should be(thread)
current.should_not be(Thread.current)
ensure
# avoids a "GC Warning: Finalization cycle" caused by *current*
# referencing the thread itself, preventing the finalizer to run:
current = nil
end
The warnings vanish when I set the process = nil as the last statement in the do_work method !