Есть ли какое-то ограничение параллелизма с обработчиками ловушек в Ruby? - PullRequest
0 голосов
/ 04 февраля 2011

Я запускаю следующий код и (одна или несколько) ловушек CLD теряется, оставляя после себя несуществующий (зомби) процесс, для которого статус выхода не был собран с помощью Process.wait

require 'pp'

children = []
trap("CLD") do
  cpid = Process.wait
  puts "CLD from pid #{cpid} at #{Time.now}"
  6.times {|i| puts "  ... Waiting[#{i}] in CLD trap for pid #{cpid}"; sleep 0.5}
  puts "OK, finished slow trap at #{Time.now} for pid #{cpid}"
  children.delete cpid
end

4.times {|i|
    if child_pid = fork # parent
      puts "In parent, child_pid[#{i}] = #{child_pid}"
      children.push child_pid
    else
      puts "In child[#{i}], PID=#{$$}"
      sleep 0.2
      puts "In child[#{i}], PID=#{$$} ... exiting"
      exit!
    end
  }

while true
  sleep 2
  exit if children.length == 0
  puts "[#{Time.now}] ... Parent still waiting for \n"
  pp children
  sleep 8
end

Вот пример выходных данных:

[admin@jcmsa pe2]# ruby multitrap.rb
In parent, child_pid[0] = 9285
In child[0], PID=9285
In parent, child_pid[1] = 9289
In child[1], PID=9289
In parent, child_pid[2] = 9293
In child[2], PID=9293
In parent, child_pid[3] = 9297
In child[3], PID=9297
In child[0], PID=9285 ... exiting
In child[3], PID=9297 ... exiting
In child[1], PID=9289 ... exiting
In child[2], PID=9293 ... exiting
CLD from pid 9285 at 2011-02-03 13:31:20 -0800
  ... Waiting[0] in CLD trap for pid 9285
CLD from pid 9289 at 2011-02-03 13:31:20 -0800
  ... Waiting[0] in CLD trap for pid 9289
CLD from pid 9293 at 2011-02-03 13:31:20 -0800
  ... Waiting[0] in CLD trap for pid 9293
  ... Waiting[1] in CLD trap for pid 9293
  ... Waiting[2] in CLD trap for pid 9293
  ... Waiting[3] in CLD trap for pid 9293
  ... Waiting[4] in CLD trap for pid 9293
  ... Waiting[5] in CLD trap for pid 9293
OK, finished slow trap at 2011-02-03 13:31:23 -0800 for pid 9293
  ... Waiting[1] in CLD trap for pid 9289
  ... Waiting[2] in CLD trap for pid 9289
  ... Waiting[3] in CLD trap for pid 9289
  ... Waiting[4] in CLD trap for pid 9289
  ... Waiting[5] in CLD trap for pid 9289
OK, finished slow trap at 2011-02-03 13:31:25 -0800 for pid 9289
  ... Waiting[1] in CLD trap for pid 9285
  ... Waiting[2] in CLD trap for pid 9285
  ... Waiting[3] in CLD trap for pid 9285
  ... Waiting[4] in CLD trap for pid 9285
  ... Waiting[5] in CLD trap for pid 9285
OK, finished slow trap at 2011-02-03 13:31:28 -0800 for pid 9285
[2011-02-03 13:31:28 -0800] ... Parent still waiting for
[9297]
[2011-02-03 13:31:38 -0800] ... Parent still waiting for
[9297]
[2011-02-03 13:31:48 -0800] ... Parent still waiting for
[9297]
[2011-02-03 13:31:58 -0800] ... Parent still waiting for
[9297]

... и так далее ...

Тогда 'ps axf' показывает

 9283 pts/2    Sl+    0:00  |   |       \_ ruby multitrap.rb
 9297 pts/2    Z+     0:00  |   |           \_ [ruby] <defunct>

В моих экспериментах

  3 children .... sometimes gets a zombie
  4 children .... more often gets a zombie
  5 children .... always gets a zombie, sometimes more than one

Какое здесь ограничение?

Как настроить обработчик прерываний CLD для обработки столько параллельных дочерних выходов, сколько мне нужно?

Версия ruby: ruby ​​1.9.1p243 (версия 2009-07-16 24175) [x86_64-linux]

Спасибо ...

Ответы [ 2 ]

1 голос
/ 04 февраля 2011

Я обратился к аналогичной проблеме в Python. В зависимости от того, как ruby ​​реализует свою обработку сигналов, вполне вероятно, что обработчик прерываний не будет вызываться снова, если дочерний процесс завершается, пока выполняется предыдущий вызов обработчика прерываний.

Таким образом, безопасным вариантом является использование цикла и получение всех возможных дочерних элементов за один запуск обработчика ловушек. Для этого предполагается, что у вас уже есть список детей, и это именно то, что вам нужно.

- ловушка (CHLD) для каждого child_pid у детей rc = waitpid (pid, WNOHANG) если получено, удалить запись из списка

0 голосов
/ 04 февраля 2011

Идиоматические рубиновые подсказки:

  1. 4.times {|i| обычно 4.times do |i| при многострочном.
  2. pp children можно заменить на "waiting for #{children.inspect}", если только вы не подразумевали две вещи в отдельных строках.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...