由于批量分叉,Ruby的“Process.fork”和“Errno :: EAGAIN”

时间:2011-04-22 11:00:02

标签: ruby exception process fork

我正在尝试使用Ruby的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 个答案:

答案 0 :(得分:1)

事实证明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)错误不再是基于这种方式提出的。

答案 1 :(得分:1)

不简单Process.waitall