需要帮助了解ruby的Process.detach

amb*_*tch 8 ruby

我正在通过ruby学习系统编程,我无法理解这种行为:

pid = fork do
  Signal.trap("USR1") do  
    puts "hello!"
  end
  Signal.trap("TERM") do
    puts "Terminating"
    exit
  end
  loop do
  end
end

Process.detach(pid)

Process.kill("USR1", pid)
Process.kill("USR1", pid)
Process.kill("USR1", pid)
Process.kill("USR1", pid)

Process.kill("TERM", pid)
Run Code Online (Sandbox Code Playgroud)

这按照我的预期输出:

hello!
hello!
hello!
hello!
Terminating
Run Code Online (Sandbox Code Playgroud)

但是,如果我注释掉Process.detach,子进程似乎只响应一次信号(并在终止后?):

Terminating
hello!
Run Code Online (Sandbox Code Playgroud)

我很困惑,为什么当我不分离过程时会发生这种情况,即使我将USR1发送了四次.有人可以帮助解释这种行为吗?我想我不明白分离流程意味着什么.

非常感谢!

Ric*_*ond 7

我怀疑这完全取决于时间 - 也就是说,差异是由于主进程和分叉进程的指令如何相对于彼此运行.

当您执行Process.detach时,将创建一个新线程,该线程等待给定进程的退出结果.您可以将Process.detach替换为

Thread.new { Process.wait(pid) }
Run Code Online (Sandbox Code Playgroud)

并获得相同的效果.我怀疑调用detach(并生成一个新线程)会给你的分叉进程带来副作用,这是一个安排的机会.

如果你没有分离,那么我猜你的分叉过程在你告诉它死的时候没有机会运行.

您可以通过在代码中插入一些睡眠调用来查看相对时间的含义,看看是否可以在没有分离的情况下获得相同的观察行为.

例如,这似乎对我有用,但您的里程可能因主机平台而异:

pid = fork do
  Signal.trap("USR1") do
    puts "hello!"
  end
  Signal.trap("TERM") do
    puts "Terminating"
    exit
  end
  loop do
  end
end

sleep(1)

Process.kill("USR1", pid)
Process.kill("USR1", pid)
Process.kill("USR1", pid)
Process.kill("USR1", pid)

sleep(1)

Process.kill("TERM", pid)
Run Code Online (Sandbox Code Playgroud)

这会产生:

hello!
hello!
hello!
hello!
Terminating
Run Code Online (Sandbox Code Playgroud)