我遇到了一个关于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实例的负载提交给固定大小的ExecutorService (35)。应用程序的其余部分等待它们全部完成-使用CountdownLatch实现。在抛出以下异常之前,一切正常运行了几个小时(Scientific Linux5.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上的搜索结果,这并不是最常见的例外,我完全不知所措。
我的猜测是,我有太多的线程试图同时启动同一个文件。然而,它需要几个小时的CPU时间来重现这个问题,所以我没有尝试使用较小的数字。
我们非常感谢您的任何建议。
发布于 2011-12-05 18:54:16
几乎可以肯定,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)来收割你死去的孩子。
如果合法运行的进程数超过了限制所允许的数量,则需要在bash(1)脚本中使用ulimit (如果以root身份运行),或者在/etc/security/limits.conf中为nproc属性设置更高的限制。
如果遇到系统范围的进程限制,则可能需要在/proc/sys/kernel/pid_max中写入一个更大的值。有关一些(简短)详细信息,请参阅proc(5)。
发布于 2011-12-05 18:46:02
errno 11表示“资源暂时不可用”这通常是内存问题,可能会阻止创建线程或套接字。
errno 12表示“无法分配内存”。这是一种获取内存失败的方法,是对内存的直接调用(而不是需要内存的资源)
我会尝试增加你系统的交换空间,这样可以避免这个问题。
https://stackoverflow.com/questions/8384000
复制相似问题