As fork
is now deprecated, I am trying to find the correct way to signal a child fiber to exit.
The old fork-based version could look like this:
child = fork do
Signal::INT.trap do
puts "child killed"
exit
end
loop do
puts "child loop"
sleep 3
end
end
begin
puts "running main"
sleep 10
ensure
puts "kill child"
child.kill(Signal::INT)
child.wait
end
When using spawn()
, the naive approach would be using a global variable instead of sending a signal:
exit_channel = Channel(Nil).new
killit = false
spawn do
loop do
break if killit
puts "child loop"
sleep 3
end
puts "child killed"
exit_channel.send(nil)
end
puts "running main"
sleep 10
puts "kill child"
killit = true
exit_channel.receive
But as far as I understand, in the (soon-to-be-default?) multi-thread mode, using a global variable is not considered safe, so we need to somehow use channels for this. The only way I could make this easily work without blocking the child fiber is by checking if a channel is closed, like this:
exit_channel = Channel(Nil).new
signal_channel = Channel(Nil).new
spawn do
loop do
break if signal_channel.closed?
puts "child loop"
sleep 3
end
puts "child killed"
exit_channel.send(nil)
end
puts "running main"
sleep 10
puts "kill child"
signal_channel.close
exit_channel.receive
Is this the right way / is there a better way of signaling a fiber without blocking it?
Best