ADDITIONAL SYSTEM INFORMATION :
Reproduced on OsX, and CentOS, Java 8 and 11.
A DESCRIPTION OF THE PROBLEM :
If while running a shutdown hook another thread will try to exit (i.e. System.exit) the machine will go into a deadlock.
A simple example:
This is because that System.exit is calling Runtime.exit which calls to Shutdown.exit which has synchronized (Shutdown.class) regardless of the status, while the Shutdown.class is already blocked y the thread that calls the shutdown hook (DestroyJavaVM)...
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the source code:
java TestShutdown.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Once the DestroyJavaVM had started, System.exit should do nothing or throw a runtime exception.
ACTUAL -
Deadlock
---------- BEGIN SOURCE ----------
public class TestShutdown {
public static void main(String[] args) throws Exception {
System.out.println("Adding shutdown");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("In shutdown");
System.out.println("Creating thread");
Thread killMe = new Thread(() -> {
System.out.println("Will exit now...");
System.exit(1);
});
System.out.println("Starting thread");
killMe.start();
System.out.println("Joinging...");
try {
killMe.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
System.out.println("Hello and goodbye");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Avoid System.exit?
Run the shutdown hook in another thread and join to it with a timeout?
FREQUENCY : always
Reproduced on OsX, and CentOS, Java 8 and 11.
A DESCRIPTION OF THE PROBLEM :
If while running a shutdown hook another thread will try to exit (i.e. System.exit) the machine will go into a deadlock.
A simple example:
This is because that System.exit is calling Runtime.exit which calls to Shutdown.exit which has synchronized (Shutdown.class) regardless of the status, while the Shutdown.class is already blocked y the thread that calls the shutdown hook (DestroyJavaVM)...
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the source code:
java TestShutdown.java
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Once the DestroyJavaVM had started, System.exit should do nothing or throw a runtime exception.
ACTUAL -
Deadlock
---------- BEGIN SOURCE ----------
public class TestShutdown {
public static void main(String[] args) throws Exception {
System.out.println("Adding shutdown");
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
System.out.println("In shutdown");
System.out.println("Creating thread");
Thread killMe = new Thread(() -> {
System.out.println("Will exit now...");
System.exit(1);
});
System.out.println("Starting thread");
killMe.start();
System.out.println("Joinging...");
try {
killMe.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}));
System.out.println("Hello and goodbye");
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Avoid System.exit?
Run the shutdown hook in another thread and join to it with a timeout?
FREQUENCY : always