2012-04-18 11 views
8

Ich bin Systemprogrammierung durch Rubin lernen, und ich habe Probleme dieses Verhalten zu verstehen:Brauchen Sie Hilfe Process.detach rubin Verständnis

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) 

Diese Ausgänge als ich erwarten:

hello! 
hello! 
hello! 
hello! 
Terminating 

Allerdings, wenn ich Kommentar aus Process.detach, scheint das Kind Prozess nur einmal auf das Signal zu reagieren (und nach Beendigung?):

Terminating 
hello! 

Ich bin verwirrt, warum das passiert, wenn ich den Prozess nicht abtrenne, obwohl ich ihn viermal gesendet habe. Kann jemand helfen, dieses Verhalten zu erklären? Ich denke, ich verstehe nicht, was es bedeutet, einen Prozess zu lösen.

Vielen Dank!

Antwort

7

Es hängt alles vom Timing ab, ich vermute - das heißt, der Unterschied liegt daran, wie die Anweisungen Ihres Hauptprozesses und des gegabelten Prozesses relativ zueinander laufen sollen.

Wenn Sie Process.detach ausführen, wird ein neuer Thread erstellt, der auf das Exit-Ergebnis des angegebenen Prozesses wartet. Sie können die Process.detach durch

ersetzen und den gleichen Effekt erhalten. Ich vermute, dass das Aufrufen von detach (und das Erstellen eines neuen Threads) Ihrem gegabelten Prozess als Nebeneffekt die Möglichkeit gibt, eingeplant zu werden.

Wenn Sie keine Trennung haben, dann würde ich meinen, dass Ihr gegabelter Prozess keine Chance hat zu laufen, wenn Sie ihm sagen, dass er sterben soll.

Sie können sehen, was ich mit relativem Timing meine, indem Sie einige Schlafaufrufe in Ihren Code einfügen, um zu sehen, ob Sie das gleiche beobachtete Verhalten ohne das Trennen erreichen können.

Zum Beispiel scheint dies für mich zu arbeiten, wenn Sie Ihre Laufleistung abhängig von der Host-Plattform variieren kann:

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) 

Dies erzeugt:

hello! 
hello! 
hello! 
hello! 
Terminating 
+0

ah, danke! Ja, ich denke, die Planung ist das, was mich verwirrt (ich bin auf OSX, sollte es auf einer virtuellen Box versuchen und sehen, was passiert). – ambertch