2010-06-16 81 views
2

給予了非常簡單的Ruby腳本:去哪個呼叫系統的信號發送去哪裏?

child = fork do 
    system 'sleep 10000' 
end 

5.times do 
    sleep 1 
    puts "send kill to #{child}" 
    Process.kill("QUIT", child) 
end 

QUIT信號只是失去了。它在哪裏?一些默認的處理程序,只是忽略它?

如何將信號發送到由該叉創建的所有進程?如果不搜索所有子進程,是否可以這樣做?

回答

7

問題是system調用創建另一個子進程在子shell中運行給定的命令,所以實際上有三個進程在你的例子中運行。此外,Ruby Kernel#system命令通過標準C函數system(3)實現,該函數調用forkexec來創建新進程,並且(在大多數系統上)忽略SIGINT和SIGQUIT,並且阻止SIGCHLD。

如果你只是打電話sleep(10000)而不是system("sleep 10000")那麼事情應該如你所願。您還可以在孩子陷阱SIGQUIT優雅地處理它:

child = fork do 
    Signal.trap("QUIT") { puts "CHILD: ok, quitting time!"; exit } 
    sleep(10000) 
end 

如果你確實需要使用從子處理的「系統」的呼叫,那麼你可能會使用一個明確的叉/ EXEC對好起來(而不是在system調用中隱含的那些),以便您可以在第三個分岔孩子中執行自己的信號處理。

0

我認爲你正在向正確的fork過程發送信號。我認爲問題出在系統命令上。系統命令會創建新的分支,並等待它結束,我認爲這個等待會阻止您的退出信號。如果你運行你的例子作爲test.rb你會看到三個過程:

  • test.rb
  • test.rb
  • 睡眠10000

如果發送信號 「術語」 或「KILL」而不是「QUIT」第二次測試.rb會死,但是睡眠10000會繼續!