java.io.IOException : error=11 异常

标签 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);
        }
}

}

whatever.sh 读取:

R --slave --args $1 $2 <whatever1.R >> r.log    

Whatever 的实例负载被提交给固定大小 (35) 的 ExecutorService。应用程序的其余部分等待所有这些完成 - 使用 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...

有人知道这是什么意思吗?根据 java.io.IOException: error=11 的 google/bing 搜索结果,这不是最常见的异常,我完全感到困惑。

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

非常感谢任何建议。

最佳答案

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

$ grep EAGAIN asm-generic/errno-base.h 
#define EAGAIN      11  /* Try again */

clone(2) 系统调用记录了一个 EAGAIN 错误返回:

   EAGAIN Too many processes are already running.

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.

如果您的内存真的那么低,它几乎肯定会显示在系统日志中。检查 dmesg(1) 输出或 /var/log/syslog 是否有任何关于系统内存不足的潜在消息。 (其他东西会坏。这似乎不太合理。)

更有可能遇到每个用户的进程限制或系统范围内的最大进程数。也许您的进程之一没有正确地重新捕获僵尸?通过随时间检查 ps(1) 输出可以很容易地发现这一点:

while true ; do ps auxw >> ~/processes ; sleep 10 ; done

(也许每分钟或十分钟检查一次是否真的需要几个小时才能遇到麻烦。)

如果您不收割僵尸,请阅读您必须对 ProcessBuilder 执行的任何操作以使用 waitpid(2) 收割您死去的 child 。

如果您合法运行的进程数超过了 rlimits 允许的数量,则需要在 bash(1) 脚本中使用 ulimit(如果运行为 root) 或在 /etc/security/limits.conf 中为 nproc 属性设置更高的限制。

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

关于java.io.IOException : error=11 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8384000/

相关文章:

java - 设置最终类属性

java - 内部类不能构造其他内部类的新实例

java - Apache Flink - 自定义 java 选项在作业中无法识别

C fork 使用与用户输入

java - 执行命令时如何获取所有错误?

java - Eclipse 插件 - 如何在命令处理程序的构造函数中注入(inject) IWorkbenchWindow

linux下如何安装mdump msend

php - 如果内存过度使用,哪个进程会被内核杀死? child 还是 parent ?

linux - libxml2 的问题原因(我无法在我的参数中访问...... wifi,蓝牙......)

shell - 如何将孤立的后台进程带回前台?