-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
P4
-
Affects Version/s: 8, 25
-
Component/s: core-libs
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Ubuntu 24.04.2 LTS (likely other Linux OSes).
Linux host 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
a Process has its streams prematurely closed during a graceful termination
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
create Shutdown.java with the contents from the "test case code" below then `javac ShutDown` && `java ShutDown`
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The logged output contains `ShutdownHook called`
ACTUAL -
the output is not present
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.concurrent.TimeUnit;
public class ShutDown {
public static Thread thread;
public static volatile boolean stopped = false;
public static void main(String[] args) throws IOException, InterruptedException {
if (args.length == 0) {
ProcessBuilder pb = new ProcessBuilder();
pb.command("java", "ShutDown", "anything");
System.err.println("Starting sub process");
Process p = pb.start();
new Thread(new StreamGobler(p.getInputStream(), System.out)).start();
new Thread(new StreamGobler(p.getErrorStream(), System.err)).start();
Thread.sleep(10_000);
System.err.println("destroying sub process");
p.destroy();
boolean exited = p.waitFor(10, TimeUnit.SECONDS);
if (exited) {
System.out.println("process exited with code:" + p.exitValue());
} else {
System.err.println("process failed to be killed");
}
} else {
Thread t = new Thread(() -> {
while (!stopped) {
System.out.print(".");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
System.out.println("Stopped");
});
System.err.println("adding shutdown hook");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.err.println("ShutdownHook called");
System.err.flush();
stopped = true;
Runtime.getRuntime().halt(22);
}));
t.start();
}
}
static class StreamGobler implements Runnable {
private final InputStream is;
private final PrintStream output;
public StreamGobler(InputStream is, PrintStream output) {
this.is = is;
this.output = output;
}
@Override
public void run() {
try {
int data = is.read();
while (data != -1) {
output.print((char) data);
data = is.read();
}
System.err.println("End of Stream");
} catch (IOException e) {
System.err.println("oopps " + e);
}
}
}
}
---------- END SOURCE ----------
Ubuntu 24.04.2 LTS (likely other Linux OSes).
Linux host 6.6.87.2-microsoft-standard-WSL2 #1 SMP PREEMPT_DYNAMIC Thu Jun 5 18:30:46 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
A DESCRIPTION OF THE PROBLEM :
a Process has its streams prematurely closed during a graceful termination
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
create Shutdown.java with the contents from the "test case code" below then `javac ShutDown` && `java ShutDown`
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The logged output contains `ShutdownHook called`
ACTUAL -
the output is not present
---------- BEGIN SOURCE ----------
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.concurrent.TimeUnit;
public class ShutDown {
public static Thread thread;
public static volatile boolean stopped = false;
public static void main(String[] args) throws IOException, InterruptedException {
if (args.length == 0) {
ProcessBuilder pb = new ProcessBuilder();
pb.command("java", "ShutDown", "anything");
System.err.println("Starting sub process");
Process p = pb.start();
new Thread(new StreamGobler(p.getInputStream(), System.out)).start();
new Thread(new StreamGobler(p.getErrorStream(), System.err)).start();
Thread.sleep(10_000);
System.err.println("destroying sub process");
p.destroy();
boolean exited = p.waitFor(10, TimeUnit.SECONDS);
if (exited) {
System.out.println("process exited with code:" + p.exitValue());
} else {
System.err.println("process failed to be killed");
}
} else {
Thread t = new Thread(() -> {
while (!stopped) {
System.out.print(".");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
System.out.println("Stopped");
});
System.err.println("adding shutdown hook");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.err.println("ShutdownHook called");
System.err.flush();
stopped = true;
Runtime.getRuntime().halt(22);
}));
t.start();
}
}
static class StreamGobler implements Runnable {
private final InputStream is;
private final PrintStream output;
public StreamGobler(InputStream is, PrintStream output) {
this.is = is;
this.output = output;
}
@Override
public void run() {
try {
int data = is.read();
while (data != -1) {
output.print((char) data);
data = is.read();
}
System.err.println("End of Stream");
} catch (IOException e) {
System.err.println("oopps " + e);
}
}
}
}
---------- END SOURCE ----------