java.io.IOException:error = 11

mba*_*rov 7 java linux process processbuilder

我遇到了一个奇怪的Java问题ProcessBuilder.代码如下所示(略微简化)

public class Whatever implements Runnable
{

public void run(){
        //someIdentifier is a randomly generated string
        String in = someIdentifier + "input.txt";
        String out = someIdentifier + "output.txt";
        ProcessBuilder builder = new ProcessBuilder("./whateveer.sh", in, out);
        try {
            Process process = builder.start();
            process.waitFor();
        } catch (IOException e) {
            log.error("Could not launch process. Command: " + builder.command(), e);
        } catch (InterruptedException ex) {
            log.error(ex);
        }
}

}
Run Code Online (Sandbox Code Playgroud)

whatever.sh读取:

R --slave --args $1 $2 <whatever1.R >> r.log    
Run Code Online (Sandbox Code Playgroud)

大量的实例Whatever被提交到ExecutorService固定大小(35).应用程序的其余部分等待所有应用程序完成 - 使用a CountdownLatch.在抛出以下异常之前,一切运行良好几个小时(Scientific Linux 5.0,java版本"1.6.0_24"):

java.io.IOException: Cannot run program "./whatever.sh": java.io.IOException: error=11, Resource temporarily unavailable
    at java.lang.ProcessBuilder.start(Unknown Source)
... rest of stack trace omitted...
Run Code Online (Sandbox Code Playgroud)

有谁知道这意味着什么?根据google/bing搜索结果java.io.IOException: error=11,它不是最常见的例外情况,我完全感到困惑.

我疯狂且没有那么受过教育的猜测是我有太多的线程试图同时启动同一个文件.但是,重现问题需要数小时的CPU时间,因此我没有尝试使用较小的数字.

任何建议都非常感谢.

sar*_*old 6

error=11几乎可以肯定是EAGAIN错误代码:

$ grep EAGAIN asm-generic/errno-base.h 
#define EAGAIN      11  /* Try again */
Run Code Online (Sandbox Code Playgroud)

clone(2)系统调用文档的EAGAIN错误回报:

   EAGAIN Too many processes are already running.
Run Code Online (Sandbox Code Playgroud)

fork(2)系统调用文档提供了两个EAGAIN错误的回报:

   EAGAIN fork() cannot allocate sufficient memory to copy the
          parent's page tables and allocate a task structure for
          the child.

   EAGAIN It was not possible to create a new process because
          the caller's RLIMIT_NPROC resource limit was
          encountered.  To exceed this limit, the process must
          have either the CAP_SYS_ADMIN or the CAP_SYS_RESOURCE
          capability.
Run Code Online (Sandbox Code Playgroud)

如果你的内存真的那么低,几乎肯定会在系统日志中显示出来.检查dmesg(1)输出或/var/log/syslog有关低系统内存的任何潜在消息.(其他事情会破裂.这似乎不太合理.)

更有可能的是,每个用户对进程的限制或系统范围的最大进程数都会遇到这种情况.也许你的一个过程没有正确收割僵尸?通过检查ps(1)输出随时间变化很容易发现:

while true ; do ps auxw >> ~/processes ; sleep 10 ; done
Run Code Online (Sandbox Code Playgroud)

(如果在遇到麻烦之前需要几个小时,也许每分钟或十分钟检查一次.)

如果你没有收获僵尸,那么请阅读你必须做的任何事情,以便ProcessBuilder waitpid(2)用来收获死去的孩子.

如果您合法地运行的进程多于您的rlimits允许的进程,则需要ulimitbash(1)脚本中使用(如果以其身份运行root)或/etc/security/limits.conf为该nproc属性设置更高的限制.

如果您遇到系统范围的进程限制,则可能需要将更大的值写入/proc/sys/kernel/pid_max.查看proc(5)一些(简短)详细信息.