我正在阅读 Jesse Storimer 的优秀书籍Working with Unix Processes。在关于从已退出的子进程捕获信号的部分中,他给出了一个代码示例。
我已经稍微修改了该代码(见下文),以便对正在发生的事情有更多的了解:
- 父母在信号之间恢复自己的执行(我可以用它看到
puts
), - 在
wait
一个语句中为多个孩子执行trap
(有时我得到“收到一个 CHLD 信号”,然后是多个“孩子 pid 退出”)。
预期产出
通常,下面代码的输出类似于:
parent is working hard
Received a CHLD signal
child pid 73408 exited
parent is working hard
parent is working hard
parent is working hard
Received a CHLD signal
child pid 73410 exited
child pid 73409 exited
All children exited - parent exiting too.
偶尔的错误
但有时我会收到这样的错误:
trapping_signals.rb:17:in `write': deadlock; recursive locking (ThreadError)
from trapping_signals.rb:17:in `puts'
from trapping_signals.rb:17:in `puts'
from trapping_signals.rb:17:in `block in <main>'
from trapping_signals.rb:17:in `call'
from trapping_signals.rb:17:in `write'
from trapping_signals.rb:17:in `puts'
from trapping_signals.rb:17:in `puts'
from trapping_signals.rb:17:in `block in <main>'
from trapping_signals.rb:40:in `call'
from trapping_signals.rb:40:in `sleep'
from trapping_signals.rb:40:in `block in <main>'
from trapping_signals.rb:38:in `loop'
from trapping_signals.rb:38:in `<main>
谁能向我解释这里出了什么问题?
编码
child_processes = 3
dead_processes = 0
# We fork 3 child processes.
child_processes.times do
fork do
# Each sleeps between 0 and 5 seconds
sleep rand(5)
end
end
# Our parent process will be busy doing some work.
# But still wants to know when one of its children exits.
# By trapping the :CHLD signal our process will be notified by the kernel
# when one of its children exits.
trap(:CHLD) do
puts "Received a CHLD signal"
# Since Process.wait queues up any data that it has for us we can ask for it
# here, since we know that one of our child processes has exited.
# We loop over a non-blocking Process.wait to ensure that any dead child
# processes are accounted for.
# Here we wait without blocking.
while pid = Process.wait(-1, Process::WNOHANG)
puts "child pid #{pid} exited"
dead_processes += 1
# We exit ourselves once all the child processes are accounted for.
if dead_processes == child_processes
puts "All children exited - parent exiting too."
exit
end
end
end
# Work it.
loop do
puts "parent is working hard"
sleep 1
end