Skip to content

Runtime shutdown hook run in the wrong place in a native image #517

@dsyer

Description

@dsyer

This code:

public class Threads {

	public static void main(String[] args) throws Exception {
		new Threads().run();
	}

	private Thread shutdownHook;

	private void run() {
		this.shutdownHook = new Thread() {
			@Override
			public void run() {
				System.err.println("Closing");
				new RuntimeException("probe").printStackTrace();
			}
		};
		Runtime.getRuntime().addShutdownHook(this.shutdownHook);
		Thread thread = new Thread(() -> {
			int i = 0;
			while (true) {
				try {
					Thread.sleep(1000L);
				}
				catch (InterruptedException e) {
					Thread.currentThread().interrupt();
					return;
				}
				System.err.println("Still here " + (i++));
			}
		});
		thread.setDaemon(false);
		thread.start();
	}
}

runs fine with the normal JDK:

$ java -cp target/classes/:target/graal-test-0.0.1-SNAPSHOT.jar Threads 
Still here 0
Still here 1
Still here 2
Still here 3
^CClosing
java.lang.RuntimeException: probe
	at Threads$1.run(Threads.java:34)

The shutdown hook is run after the end of all the other threads. When you compile to a native image the shutdown hook gets run out of order (first, it seems, before any other threads):

$ ./threads 
Closing
java.lang.RuntimeException: probe
	at java.lang.Throwable.<init>(Throwable.java:265)
	at java.lang.Exception.<init>(Exception.java:66)
	at java.lang.RuntimeException.<init>(RuntimeException.java:62)
	at Threads$1.run(Threads.java:34)
	at com.oracle.svm.core.jdk.Util_java_lang_ApplicationShutdownHooks.callRunnableOfThread(JavaLangSubstitutions.java:656)
	at com.oracle.svm.core.jdk.Target_java_lang_ApplicationShutdownHooks.runHooks(JavaLangSubstitutions.java:576)
	at com.oracle.svm.core.jdk.Util_java_lang_ApplicationShutdownHooks$1.run(JavaLangSubstitutions.java:637)
	at java.lang.Shutdown.runHooks(Shutdown.java:123)
	at java.lang.Shutdown.sequence(Shutdown.java:167)
	at java.lang.Shutdown.shutdown(Shutdown.java:234)
	at com.oracle.svm.core.jdk.RuntimeSupport.shutdown(RuntimeSupport.java:183)
	at com.oracle.svm.core.JavaMainWrapper.run(JavaMainWrapper.java:179)
Still here 0
Still here 1
Still here 2
Still here 3

This obviously causes problems for programs that actually clean up resources in a shutdown hook.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions