Что может привести к блокировке ReadableByteChannel.close ()? - PullRequest
2 голосов
/ 21 июля 2011

Я пытаюсь запустить внешний процесс с таймаутом и прочитать все выходные данные, которые он выдает.Это оказывается на удивление геркулесовой задачей.Моя основная стратегия состоит в том, чтобы запустить процесс с использованием ProcessBuilder и прочитать его вывод в главном потоке.Другой поток обрабатывается, ожидая истечения времени ожидания и (при необходимости) вызвать метод close () для канала ReadableByteChannel, который я ему передал, вызов destroy () для процесса, который также был передан ему.

Похоже, это прекрасно работает в процессе, который печатает бесконечный вывод, даже получая ожидаемое исключение AsynchronousCloseException.Тем не менее, при тестировании против программы, которая просто бесконечно спит, блоки потоков закрываются:

private void terminateProcess() {
    try {
        System.out.println("About to close readChannel.");
        readChannel.close();
        System.out.println("Closed the readChannel.");
    } catch (IOException e) {
        // Not relevant
    }
}

Я никогда не вижу второй оператор печати, и мой тест зависает навсегда.Javadoc говорит, что close () может блокировать, если выполняется другое закрытие, но в моем коде нет других вызовов close ().Что еще может вызвать это?

1 Ответ

3 голосов
/ 22 июля 2011

Причина, по которой тест зависает навсегда, состоит в том, что ReadableByteChannel.close () будет блокироваться, если ReadableByteChannel.read () блокирует его.

Из документации ReadableByteChannel в режиме блокировки (все каналы по умолчанию) будут блокироваться, пока не будет прочитан хотя бы один байт, если в вашем ByteBuffer есть свободный байт, поэтому чтение будет блокироваться.

Если вы прочитаете код для класса java.nio.channels.Channels $ ReadableByteChannelImpl (найденный в Channels.java), вы увидите, что ReadableByteChannelImpl прокомментирован как «На самом деле не прерываемый» - и, по-видимому, они это имеют в виду.

Если вы вызываете Process.destroy (), это завершит Process, который не произвел никакого ввода, и вызовет исключение AsynchronousCloseException из потока чтения.

...