ruby - 为什么线程中分叉进程的存在会改变陷阱块内的睡眠行为?
问题描述
这按预期工作:
signals = %w[INT TERM]
signals.each do |signal|
Signal.trap(signal) do
puts "trapping the signal and sleeping for 5 seconds"
sleep 5
puts "done, exiting"
exit
end
end
sleep 100
这样做:
# ...signal trap code from above...
t = Thread.new{ sleep 10 }
t.join
这样做:
# ...signal trap code from above...
`sleep 10`
但是,这不会:
# ...signal trap code from above...
t = Thread.new{ `sleep 10` }
t.join
对于前三个,启动代码然后立即发送control-c
结果在 ruby 等待 5 秒后退出。
第四,启动代码,然后立即发送control-c
结果,ruby 立即退出。令人惊奇的是puts
,“trapping the...”和“done...”这两条消息都被打印出来了,但sleep 5
它们之间的信息似乎被跳过了。
使用 terrapin 而不是反引号会产生另一个线索 - terrapin 抱怨子进程以非零状态退出。尝试打印此状态时,它什么也不打印,可能表明该进程被毫不客气地硬杀死。
因此,对于在不是主线程的线程中创建的子进程,ruby 似乎具有某种默认行为。我怀疑这可能是设计使然,但我找不到任何有关它的文档或讨论。
我也试过
t = Thread.new{ `ls -R /` }
而不是睡眠,以防万一与竞争睡眠实现有某种交互,相同的行为。
为什么会这样?
更多实验
这也按预期运行。它等待线程内的子进程完成 10 秒。所以,奇怪的行为只发生在信号陷阱的情况下。
thread = Thread.new { `sleep 10` }
thread.join
测试是否正在发生涉及子线程同时捕获信号的事情,无论是通过设计还是由于错误。但这表现如预期:
@main_thread = Thread.current.object_id
puts "main thread: #{@main_thread}"
signals = %w[INT TERM]
signals.each do |signal|
Signal.trap(signal) do
puts Thread.current.object_id
next unless Thread.current.object_id == @main_thread
puts "thread from trap: #{Thread.current.object_id}"
puts "trapping the signal and sleeping for 5 seconds"
sleep 5
puts "done, exiting"
exit
end
end
解决方案
推荐阅读
- c# - 在 Blazor 服务器端使用 HttpClient 获取 StatusCode 407 AuthenticationRequired
- xslt - XLST - 根据长度很好地将长地址拆分为多个标签
- python - 什么是 open cv pts 数据类型?
- amazon-web-services - 无法使用 Java Sdk 创建 Aws Emr 集群
- javascript - 我怎样才能减少这种jQuery?
- python - 如何将整数列表转换为单个整数?
- jhipster - 用 Jhipster 开发 Bot 系统?
- vuejs2 - 在无效凭据上出现未捕获(承诺)NavigationDuplicated 错误
- javascript - Ag-Grid 动态设置列和行数据
- python-3.x - 获取单个属性值