Зависание процесса Java/выполнения ввода-вывода

Вот мой рабочий процесс:

Я получаю задание из БД, запускаю несколько задач, запускаю внешнюю программу, которая читает файл и создает другой (обычно это занимает менее 10 секунд). Вот код:

Process p = Runtime.getRuntime().exec(prog, null, new File(path));

BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));

String s;
String errorString = "";
while((s = stdInput.readLine()) != null) {
    if(s.toLowerCase().contains("error")) {
        Log.writeLog("error: " + s);
        errorString += s + "\r\n";
    }
}

if(errorString.length() > 1) {
    Emailer.email(name + "*" + errorString, "ERROR");
}

while((s = stdError.readLine()) != null) {
    Log.writeLog("ERROR: " + s);
}

Однако фрагмент завис. Я контролирую сервер, на котором выполняется код, через LogMeIn, после входа в систему процесс разблокируется (общее время выполнения около 280 секунд) и продолжается. Процесс не дал результатов ERROR. Это случается время от времени чаще, чем хотелось бы. Мы выполняем довольно много небольших операций ввода-вывода в программе, и жесткий диск время от времени заполняется.

Любая идея, что может происходить?

Спасибо!

РЕДАКТИРОВАТЬ: сервер — это обычный компьютер, подключенный к LogMeIn. Я боюсь, что, поскольку это обычный компьютер, он может отключить процессор / жесткий диск, когда он не используется (не уверен, что это правильная терминология). Это несколько объясняет, почему это продолжалось, как только я вошел в LogMeIn и получил доступ к компьютеру.

EDIT2: сразу после процесса я запускаю это. И это также зависает на абсурдное количество времени (обычно 5 секунд, заняло 200+ секунд). Сдается мне, что жесткий диск решил вздремнуть?

private void cleanup(String path) {

    File srcPath = new File(path);
    File[] files = srcPath.listFiles();

    if(files != null) {
        for(File file : files) {
            if(file.isDirectory()) {
                cleanup(file.getAbsolutePath());
            } else {
                if(file.getAbsolutePath().endsWith(".original")) {
                    String fileName = file.getAbsolutePath().substring(0,     file.getAbsolutePath().lastIndexOf(".original"));
                    IO.delete(fileName);
                    if(!IO.renameFile(file.getAbsolutePath(), new File(fileName).getAbsolutePath())) {
                        Log.writeLogSevere("Failed to rename file, this could be a problem..." + fileName);
                    } else {
                        Log.writeLog("Cleaned up: " + fileName);
                    }
                }
            }
        }
    }
}

person jn1kk    schedule 07.08.2013    source источник
comment
в лог файле ничего нет?   -  person Graham Griffiths    schedule 07.08.2013
comment
@GrahamGriffiths в журнале ничего нет, электронных писем тоже.   -  person jn1kk    schedule 07.08.2013
comment
Я предполагаю, что процесс, который вы вызываете, зависает - можете ли вы проверить, что он все еще работает? Это может быть тайм-аут БД?   -  person Graham Griffiths    schedule 07.08.2013
comment
@GrahamGriffiths, я не помню на 100%. Но я считаю, что процесс все еще работает, что, я думаю, объясняет, что проблема может быть не в Java. Внешний процесс не выполняет ничего, кроме операций ввода-вывода и математических вычислений в этом файле.   -  person jn1kk    schedule 07.08.2013
comment
может быть связано: stackoverflow.com/questions/8595748/java-runtime-exec   -  person Graham Griffiths    schedule 07.08.2013


Ответы (2)


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

Вы должны либо использовать для этого отдельный поток, либо (гораздо проще) redirectErrorStream с использованием ProcessBuilder.

person Marko Topolnik    schedule 07.08.2013
comment
В конечном итоге процесс завершился, когда я получил контроль над сервером через LogMeIn. В журнал ничего не было записано, что, по-видимому, предполагает, что ErrorStream был пуст. Я все же вставлю это. - person jn1kk; 07.08.2013

Скорее всего, поток, выполняющий p, не умер, а p.getInputStream() не нуль, но не данные о нем.

Пока он висит, я бы проверил текущие запущенные процессы (команда ps в Unix) или диспетчер задач в Windows. Это скажет вам, выполнено ли p или нет. Если это не так, то какой бы ни была эта программа, у нее есть проблемы, и она задерживает остальную часть вашего кода.

person mprivat    schedule 07.08.2013