Как убить дочерний процесс, порожденный Java, когда Tomcat выключен - PullRequest
4 голосов
/ 30 ноября 2011

Я написал сервис для JIRA (веб-приложение, работающее на tomcat), который запускается периодически (скажем, 1 час).По сути, служба выполняет системную команду через runtime.exec(command) и анализирует выходные данные, сгенерированные этой командой, а затем обновляет индекс Lucene, и выходные данные будут огромными.

Проблемы:

1) Если я отключу tomcat с помощью shutdown.sh во время выполнения вышеуказанного сервиса, процесс java (или catalina) не будет уничтожен.И java, и дочерний процесс живут некоторое время, то есть до тех пор, пока системная команда не завершит & service не обработает вывод.Но затем службе не удается обновить индекс, оставляя индекс в несовместимом состоянии.

Если я выключаю tomcat, когда вышеуказанная служба не запущена, все хорошо.Я думаю, это объясняется здесь .Я до сих пор не понимаю, почему JVM не отключается, так как вышеуказанный сервис работает в tomcat?

Обратите внимание, что это единственное java-приложение, работающее на этом компьютере.

2) Затем, если я убью java с помощью kill <pid>, оба процесса java и child будут уничтожены, что противоречит этот пост .

Это потому, что дочерний процесс отправляет вывод родительскому элементу (java) и после того, как родительский объект убит, дочерний процесс не знает, куда отправить вывод и, таким образом, был убит?пытался использовать shutdownhook , как объяснено в этом посте , но это не работает для меня.Код внутри shutdownhook выполняется только после того, как процессы java и child завершены с их работой.Таким образом, вызов process.destroy() внутри shutdownhook здесь бесполезен.

Это кажется очевидным, поскольку JVM все еще работает в моем случае, он не будет вызывать shutdownhooks, пока не запустит свою последовательность выключения.Не знаю, как это работает для другого парня, я имею в виду, почему дочерний процесс, порожденный Java, все еще работает, когда JVM не работает.

4) Если я перезапущу tomcat, новый процесс Java с другим pid

Можно ли программно остановить дочерний процесс при отключении tomcat?

Дайте мне знать, если мне не понятно мое объяснение ...

Здеськод, который выполняет системную команду:

        String command = getCommand();

        File view = new File(viewPath);
        Runtime runtime = Runtime.getRuntime();
        try
        {
            final Process process = runtime.exec(command, null, view);

            StreamReader errorStreamReader = new StreamReader(process
                .getErrorStream());
            Thread errorStreamThread = new Thread(errorStreamReader);
            errorStreamThread.start();
            revisions = parseRevisionLogs(process.getInputStream());

            process.waitFor();

            process.getInputStream().close();
            process.getErrorStream().close();
            process.getOutputStream().close();
        }

Ответы [ 3 ]

3 голосов
/ 30 ноября 2011

JVM не отключится, если оставшиеся потоки не будут помечены как «демон».Любые пользовательские потоки, не являющиеся демонами, должны завершиться до выхода из JVM.См. этот вопрос .Если ваши периодические задачи не установлены с setDaemon(true), то они должны будут завершиться до выхода JVM.Вы должны позвонить setDaemon до начала процесса.

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

2 голосов
/ 30 ноября 2011

Я бы посоветовал вам сделать следующее.

Не читать выходные данные процесса непосредственно из Java. Вместо этого перенаправьте вывод в файл и прочитайте его оттуда, когда процесс завершится. Оберните вашу команду, используя командный файл или скрипт оболочки, в котором хранится PID отдельного процесса, чтобы вы могли убить этот процесс отдельно. Теперь добавьте хук отключения к tomcat, который будет запускать kill PID, где PID - это идентификатор процесса отдельного процесса.

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

Удачи.

0 голосов
/ 30 ноября 2011

Вы делаете waitFor () для процесса?

Если это так, вы можете поймать InterruptedException и до p.destroy()

...