If a process created in java creates a sub-process, but then returns, the JVM hangs, but with no process id.
Example application below (requires Windows and Java 7)
import java.io.File;
import java.io.IOException;
import java.lang.ProcessBuilder.Redirect;
import java.nio.file.Files;
public class SubProcessHang {
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder builder = new ProcessBuilder("cmd", "/c", "start", "notepad.exe");
File output = Files.createTempFile("output", "txt").toFile();
builder.redirectError(Redirect.to(output));
builder.redirectOutput(Redirect.to(output));
Process process = builder.start();
process.waitFor();
int exitValue = process.exitValue();
System.out.println("Process exit value:: " + exitValue);
System.out.println("Output file length:: " + output.length());
System.exit(exitValue);
}
}
When the application runs, it creates three processes: java --> cmd --> notepad cmd immediately returns and java calls System.exit(0), which kills the java process. But notepad is still there, and, when run from gradle (or eclipse for that matter,) the JVM hangs around until that process goes away, not returning it's return value.
So the children process is still alive but the parent process has been partially killed, but is now stranded forever.
The build.gradle script to reproduce this
apply plugin: 'java'
apply plugin: 'application'
mainClassName = "SubProcessHang"
Execute 'gradle run' and get this output:
C:\HangDemo>gradlew run
:compileJava
:processResources UP-TO-DATE
:classes
:run
Process exit value:: 0
Output file length:: 0
> Building 75% > :run
I know it must have something to do with how the java processes are created, but I have no idea what to do.
What can I do short of getting the ID of the running java process and killing all sub-processes in a shutdown hook?
The docs for Process say
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.
http://docs.oracle.com/javase/7/docs/api/java/lang/Process.html
Maybe your process is creating stdout or stderr output. Try draining the InputStream and the ErrorStream.
I would say that this answer might help with getting the sub-process IDs and this one - with killing them in Windows environment.
Hope that helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With