2010-06-16 7 views
2

un script Étant donné rubis très simple:Où va le signal envoyé au processus qui a appelé le système?

child = fork do 
    system 'sleep 10000' 
end 

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

QUIT est le signal vient de perdre. Où est-ce que ça va? Quelque chose avec le gestionnaire par défaut qui l'ignore simplement? Comment envoyer un signal à tous les processus créés par cette fourchette? Est-il possible de faire cela sans rechercher tous les processus enfants?

Répondre

7

Le problème est que l'appel system crée encore un autre processus enfant exécutant la commande donnée dans un sous-shell, il y a donc trois processus en cours d'exécution dans votre exemple. De plus, la commande Ruby Kernel#system est implémentée via la fonction C standard system(3), qui appelle fork et exec pour créer le nouveau processus et (sur la plupart des systèmes) ignore SIGINT et SIGQUIT et bloque SIGCHLD.

Si vous appelez simplement sleep(10000) au lieu de system("sleep 10000") alors les choses devraient fonctionner comme prévu. Vous pouvez également piège SIGQUIT chez l'enfant de le manipuler grâce:

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

Si vous avez vraiment besoin d'utiliser un appel « système » du processus d'enfant alors vous pourriez être mieux à l'aide d'une paire de fourche explicite/exec (au lieu des appels implicites dans l'appel system), de sorte que vous pouvez effectuer votre propre gestion du signal dans le troisième enfant forké.

0

Je pense que vous envoyez le signal au processus de fourche corectly. Je pense que le problème est avec la commande système. La commande System crée une nouvelle fourchette et attend jusqu'à la fin et je pense que cette attente bloque votre signal de sortie. Si vous exécutez votre exemple que test.rb vous verrez trois processus:

  • test.rb
  • test.rb
  • sommeil 10000

Si vous envoyez le signal "TERME" ou "KILL" au lieu de "QUIT" le second test.rb va mourir mais dormir 10000 continuera!

Questions connexes