Куда идет сигнал, отправленный процессу, который называется системой? - PullRequest
2 голосов
/ 16 июня 2010

С учетом очень простого сценария ruby:

child = fork do
  system 'sleep 10000'
end

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

Сигнал QUIT просто потерян.Куда это идет?Что-то с обработчиком по умолчанию, который просто игнорирует это?

Как отправить сигнал всем процессам, созданным этим форком?Возможно ли это сделать без поиска всех дочерних процессов?

Ответы [ 2 ]

7 голосов
/ 23 июня 2010

Проблема в том, что вызов system создает еще один дочерний процесс, выполняющий данную команду в подоболочке, поэтому в вашем примере фактически выполняются три процесса. Кроме того, команда Ruby Kernel#system реализована через стандартную функцию C system (3) , которая вызывает fork и exec для создания нового процесса и (в большинстве систем) игнорирует SIGINT и SIGQUIT и блокирует SIGCHLD.

Если вы просто позвоните sleep(10000) вместо system("sleep 10000"), тогда все должно работать так, как вы ожидаете. Вы также можете поймать SIGQUIT в ребенка, чтобы изящно с ним справиться:

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

Если вам действительно нужно использовать «системный» вызов от дочернего процесса, то вам может быть лучше использовать явную пару fork / exec (вместо неявных в вызове system), чтобы вы могли выполнить Ваша собственная обработка сигналов у третьего разветвленного ребенка.

0 голосов
/ 16 июня 2010

Я думаю, что вы отправляете сигнал на форк процесс. Я думаю, что проблема с системной командой. Системная команда создает новый форк и ждет, пока он не закончится, и я думаю, что это ожидание блокирует ваш сигнал выхода. Если вы запустите свой пример как test.rb, вы увидите три процесса:

  • test.rb
  • test.rb
  • Сон 10000

Если вы отправите сигнал «TERM» или «KILL» вместо «QUIT», второй test.rb умрет, но сон 10000 продолжится!

...