How to kill a child process generated by Java when tomcat is completed

I wrote a service for JIRA (the web application runs on tomcat) that runs periodically (say, 1 hour). In principle, the service executes the command command through runtime.exec(command) and analyzes the result generated by the command, then updates the Lucene index, the output will be huge.

Problems:

1) If I quit tomcat with shutdown.sh while the above service is running, the java (or catalina) process is not killed. Both java and the child process live for some time, that is, until the system command completes its work and processes the output process. But then the service does not update the index, leaving the index in an inconsistent state.

If I turn off tomcat when the above service is not running, everything will be fine. I think this is explained here . I still do not understand why the JVM will not shut down, since the above service works in tomcat?

Please note that this is the only java application running on this machine.

2) Then, if I destroy java with kill <pid> , both java and the child process will be killed, which contradicts this post .

This is because the child process sends the result to the parent (java), and as soon as the parent is killed, the child has no idea where to send the output and, thus, was killed?

3) I tried using shutdownhook as described in this post , but this does not work for me. The code inside shutdownhook launched only after java and its child processes run. Thus, calling process.destroy() inside the shutdownhook is not useful here.

This seems obvious, since the JVM is still working in my case, it will not call shutdownhooks until it starts to shut it down. I don’t know how this worked for another guy, I mean, why the child process created by java still works when the JVM is not working.

4) If I restart tomcat, a new java process with a different pid is generated.

Is it possible to programmatically stop the child process when tomcat shuts down?

Let me know if I do not understand, with my explanation ...

Here is the code that executes the system command:

  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(); } 
+4
source share
3 answers

The JVM will not complete if the remaining threads are marked as "daemon". Any beggar user threads must terminate before the JVM is released. See this question . If your periodic jobs are not set using setDaemon(true) , they will have to finish before the JVM setDaemon(true) out. You must call setDaemon before starting the process.

You should be able to do your periodic daemon tasks, however you do have a race condition with the JVM turned off. You might think that a single daemon task was reading from a process, but a non-daemon task would update the index, which probably should not be killed during its operation.

Then your thread without a daemon could sleep, waiting for the download and testing to complete, to check if it should end with a volatile boolean field or another signal.

+3
source

I suggest you do the following.

Do not read the 'output process directly from java. Instead, redirect the output to a file and read it there when the process ends. Wrap your command with a batch file or shell script that stores the PID of a separate process so that you can kill this process separately. Now add a hookdown for tomcat, which will launch kill PID , where PID is the process ID of the individual process.

I believe this will work, because now your tomcat and the separate process are completely decoupled, so nothing prevents tomcat from shutting down. The same goes for the process.

Good luck.

+2
source

Are you doing waitFor () in the process?

If so, you can catch an InterruptedException and

0
source

Source: https://habr.com/ru/post/1383872/


All Articles