поток Java, ожидающий завершения мертвого процесса - PullRequest
5 голосов
/ 15 февраля 2012

Я написал Java-класс для выполнения многопоточных задач, каждая из которых выполнялась внешним процессом. Процесс отвечает за преобразование файлов ".chp" в файлы ".txt". Это написано в C.

Этот процесс прерывается в один момент, потому что он исчезает, если посмотреть на «верх» в моем терминале (возможно, из-за поврежденного файла chp). Проблема в том, что процесс в моем потоке Java не возвращается. «Process.waitFor ()», кажется, продолжается вечно (по крайней мере, до 12 часов, которые я указал для ExecutorService.

Я что-то делаю не так (не ловит исключение?)? Я попытался установить переменную класса типа String в MyThread и поместить сообщение об ошибке вместо создания нового RuntimeException, а затем вывести строку в конце основного, но код потока не достигнет этой точки. Это все еще застревает в waitFor ().

Не должен ли процесс завершиться после сбоя программы на С?

Программа печатает на терминале (ср .: MyThread):

A
B
C

основной:

String pathToBin = "/path/to/bin";
List<MyThread> threadList = new ArrayList<MyThread>();

for (File f : folderList) {
    File[] chpFilesInFolder = f.listFiles(new FilenameFilter() {

        @Override
        public boolean accept(File dir, String name) {
            if (name.endsWith(".chp")){
                 return true;
            }else{
                 return false;
            }
        }
    });
    File chpFile = writeChpFiles(chpFilesInFolder);
    String[] cmd = {pathToBin, "--arg1", chpFile, "--out-dir", outputFolder};
    MyThread t = new MyThread(cmd, f, chpFilesInFolder);
    threadList.add(t);
}

ExecutorService threadExecutor = Executors.newFixedThreadPool(4);
for(MyThread th : threadList){
    threadExecutor.execute(th);
}
threadExecutor.shutdown();

try {
    threadExecutor.awaitTermination(12, TimeUnit.HOURS);
} catch (InterruptedException e) {
    e.printStackTrace();
}

MyThread:

class MyThread extends Thread{
    private String[] cmd;
    private File chpFolder;
    private File[] chpFilesInFolder;

    public MyThread(String[] cmd, File chpFolder, File[] chpFilesInFolder){
        this.cmd = cmd;
        this.chpFolder = chpFolder;
        this.chpFilesInFolder = chpFilesInFolder;
    }

    @Override
    public void run() {
        Process process = null;
        try{
            System.err.println("A ");
            ProcessBuilder procBuilder = new ProcessBuilder(cmd);
            procBuilder.redirectErrorStream(true);

            System.err.println("B");
            process = procBuilder.start();

            System.err.println("C");
            process.waitFor();

            System.err.println("D");
            if(process.exitValue()!=0) System.err.println("ERROR !"+process.exitValue());

            System.err.println("E");
        }catch(IOException e){
            e.printStackTrace();
        }catch(InterruptedException e){
            e.printStackTrace();
        }catch(Throwable e){
            e.printStackTrace();
        }finally{
            System.err.println("F");
            if(process!=null) {try { process.destroy();} catch(Exception err) {err.printStackTrace();}}
        }

        File[] txtFilesInFolder = chpFolder.listFiles(new FilenameFilter() {

            @Override
            public boolean accept(File dir, String name) {
                if (name.endsWith(".chp.txt")){
                    return true;
                }else{
                    return false;
                }
            }
        });

        if (txtFilesInFolder.length==chpFilesInFolder.length){
            for (File chp : chpFilesInFolder) {
                chp.delete();
            }
            File logFile = new File(chpFolder, "apt-chp-to-txt.log");
               if (logFile.exists()){
                   logFile.delete();
               }
        }else{
            throw new RuntimeException("CHPs have not all been transformed to TXT in "+chpFolder.getAbsolutePath());
        }

Ответы [ 5 ]

3 голосов
/ 23 февраля 2012

Возможно ли, что ваша программа C производит вывод на стандартный вывод?Если это так, вам нужно прочитать Process.getOutputStream (), прежде чем Process.waitFor () вернется - см. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4254231

В качестве альтернативы, вызовите вашу программу на C, чтобы это был сценарий оболочки, перенаправляющий stdout.

Вы можете использовать команду jstack, чтобы подтвердить, что поток действительно заблокирован в Process.waitFor ().

0 голосов
/ 15 февраля 2012

Запуск внешних процессов в Java может быть немного сложнее. Я обычно стараюсь их избегать, так как вам придется иметь дело с разными кодами ошибок и каким-то терминальным безумием. Я рекомендую вам использовать специализированные библиотеки, такие как commons-exec (http://commons.apache.org/exec/)

0 голосов
/ 15 февраля 2012

Если я правильно понял, ваши потоки Java продолжают ждать после сбоя программы C.

Заставить порожденный процесс C отправить сердцебиение.Вы можете сделать это, даже напечатав sth на консоль (или вставив в таблицу) и периодически вызывая нить Java и проверяя сердцебиение.Если его там нет, предположим, что процесс C умер, и завершите поток.

0 голосов
/ 15 февраля 2012

Как бы часто я ни предлагал использовать более надежную и профессиональную точку зрения при использовании решения для обмена сообщениями, чтобы заставить вашу C-программу взаимодействовать с вашим Java-приложением, будет легко и чисто избежать того, что потоки, не являющиеся демонами, будут ждать вечно, потому чтосбоя вашего приложения на C ... теперь у всех брокеров есть интерфейс STOMP, который очень удобен для вызова любого типа приложения (просто используйте любую библиотеку Http), конфигурация брокера позволит перезапустить незавершенные задания, установить некоторые тайм-аутыи так одно ... Даже если JMS не поддерживает запрос и ответ, довольно легко реализовать такую ​​парадигму ....

HTH Джером

0 голосов
/ 15 февраля 2012

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...