TL; DR
v1.16.0 から、 parallel の gem 使ってるときに timeout とか使って親を殺しても、ちゃんと子供達も kill されるようになりました。
詳細
parallel の gem は、便利なんだけれども、親スレッドを kill してもその子供達は普通に活動し続ける。 thread であろうとも process であろうとも。
例:
t = Thread.new do
Parallel.map(0..1000, in_threads: 2) do |i|
p i
sleep 1
end
end
sleep 1
t.kill
sleep
# 0
# 1
# 3
# 2
# 5
# 4
# => kill しているにも関わらず 1000 まで出力される。
たとえば、悪名高い timeout と組み合わせるとこうなる。
begin
Timeout.timeout(1) do
Parallel.map(0..1000, in_threads: 2) do |i|
p i
sleep 1
end
end
rescue Timeout::Error
p :timeout
end
sleep
# 0
# 1
# 2
# 3
# :timeout
# 4
# 5
# 6
# 7
# 8
# => 1000 まで続く
これは、あんまりにもあれなので、 parallel 本家に以下の PR を出してマージしてもらった。
これによって、 Timeout やら 親スレッドの kill やらが行われた時に、その子供のスレッドやプロセスについても正しく kill されるようになった。
begin
Timeout.timeout(1) do
Parallel.map(0..1000, in_threads: 2) do |i|
p i
sleep 1
end
end
rescue Timeout::Error
p :timeout
end
sleep
# 0
# 1
# 3
# :timeout
# 2
# => ここでとまる
Concurrent Ruby を使えよ、という話は若干ある