java.io.IOException: ошибка = 11 - PullRequest
       11

java.io.IOException: ошибка = 11

7 голосов
/ 05 декабря 2011

У меня странная проблема с 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);
        }
}

}

what.sh читает:

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

Нагрузки экземпляров Whatever передаются в ExecutorService фиксированного размера (35). Остальная часть приложения ожидает завершения всех их действий - 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...

У кого-нибудь есть идея, что это значит? Судя по результатам поиска в Google / Bing для java.io.IOException: error=11, это не самое распространенное исключение, и я совершенно сбит с толку.

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

Любые предложения приветствуются.

Ответы [ 2 ]

6 голосов
/ 05 декабря 2011

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), чтобы пожинать своих мертвых детей.

Если вы на законных основаниях выполняете больше процессов, чем позволяют ваши rlimitsвам нужно будет использовать ulimit в ваших bash(1) сценариях (если выполняется как root) или установить более высокие ограничения в /etc/security/limits.conf для свойства nproc.

Если вы вместо этого запускаетев рамках общесистемных ограничений процесса может потребоваться записать большее значение в /proc/sys/kernel/pid_max.См. proc(5) для некоторых (коротких) деталей.

2 голосов
/ 05 декабря 2011

errno 11 означает «Ресурс временно недоступен». Обычно это проблема с памятью, которая может помешать созданию потока или сокета.

errno 12 означает «Не удается выделить память». Это ошибка при получении памяти - это прямой вызов памяти (а не ресурса, который в свою очередь нуждается в памяти)

Я бы попытался увеличить пространство подкачки вашей системы, чтобы избежать этой проблемы.

...