Ruby `Process.fork` и` Errno :: EAGAIN` из-за пакетного разветвления - PullRequest
0 голосов
/ 22 апреля 2011

Я пытаюсь что-то сделать, используя Process.fork Руби. Однако через несколько секунд появится следующее исключение: fork: Resource temporarily unavailable - fork(2) (Errno::EAGAIN)

Из того, что я понимаю, после проведения некоторых исследований выяснилось, что ОС имеет ограничение на количество процессов, которые могут быть запущены в ОС. И вышеупомянутая ошибка указывает, что предел был превышен из того, что я прочитал.

Однако я не понимаю, как этот предел превышается, в то время как я явно Process.wait в конце, чтобы все дочерние процессы завершили работу перед повторным циклом одного и того же кода. Первые 10 или около того циклов он работает нормально, но после этого fork: Resource temporarily unavailable - fork(2) (Errno::EAGAIN) снова показывает себя.

Вот простой пример того, что я делаю:

loop do
  records = MyDatabase.find_batch_of_25_records_to_process_concurrently
  records.each do |record|
    Process.fork do # Spawn 25 child processes, one for each record
      record.process!
    end
  end

  Process.wait # wait until 25 Child Processes are finished/killed (, right?)
  sleep 5
end

Итак, я получаю 25 записей из своей базы данных, а затем хочу обрабатывать их одновременно. Поэтому я перебираю каждую запись и разрабатываю процесс для каждой из них. В конечном итоге основной процесс разветвляется 25 раз. Затем я вызываю Process.wait, чтобы он не повторялся до тех пор, пока все дочерние процессы не будут завершены. Затем он будет спать в течение 5 секунд и повторять процесс, повторно разветвляясь на 25 новых дочерних процессов и т. Д.

Кто-нибудь знает, почему после пары циклов возникает эта ошибка (fork: Resource temporarily unavailable - fork(2) (Errno::EAGAIN))? И, надеюсь, как это предотвратить? Глядя на мой ActivityMonitor, я вижу, что появляются 25 новых процессов Ruby. Затем через 2 или около того секунды все они снова исчезают, потому что они закончили свои задачи. Затем в мониторе активности появятся 25 новых процессов, а затем снова исчезнут. Поэтому я предполагаю, что они на самом деле порождены и убиты, но ошибка все еще возникает.

Любая обратная связь высоко ценится, спасибо!

Ответы [ 2 ]

1 голос
/ 04 октября 2011

не проще Process.waitall?

1 голос
/ 22 апреля 2011

Оказывается, что Process.wait является причиной этой проблемы. Я думаю, что это может не правильно зарегистрировать дочерний процесс как «завершенный» таким образом.

То, что я закончил, было следующим:

loop do
  pids    = Array.new # Create a local variable to hold an array of pids
  records = MyDatabase.find_batch_of_25_records_to_process_concurrently
  records.each do |record|
    pids << Process.fork do # Fork a child, and add it's returned pid to the array
      record.process!
    end
  end

  pids.each do |pid|
    Process.wait(pid) # Explicitly wait for **each** pid individually
  end
  sleep 5
end

Кажется, что это работает нормально и больше не падает с 10 секундами. Я собираюсь оставить это на время и посмотреть, не закончится ли это в конце концов. В любом случае, до сих пор похоже, что ошибка fork: Resource temporarily unavailable - fork(2) (Errno::EAGAIN) больше не основана на этом.

...