Reputation: 60768
My problem is that my shutdown is happening too early, without waiting for the process to clean itself up.
However, if in my shutdown Thread I add a while(true) Thread.sleep(1000);
, the process cleans up fine, and obviously, never shuts down.
This is confusing to me since the shutdown completes before many non-daemon threads are complete. For example, if I write a very simple test program in which the main()
infinite-loops and the shutdown thread doesn't, main
will be terminated anyway (without any exception trace coming from catching InterruptedException
s).
So as far as I can tell the shutdown happens when the shutdown thread run
method completes. I think from this knowledge I can fix this by ending it in a poll loop, polling for a Future
that denotes successful shutdown of the rest of my processes. But this seems wrong - I really just want to wait for all non-daemon threads to shutdown, and I certainly don't want to do a poll.
run
method completes?Upvotes: 2
Views: 1880
Reputation: 328594
Generally, a Java process can stop after all non-daemon threads have terminated. This is usually the time when the VM will invoke the shutdown hooks.
The hooks will be called early (i.e. with some non-daemon threads still around) if you kill the process or call System.exit()
If I understand you correctly, you try to do something after all other non-daemon threads have finished (i.e. wait for all other shutdown threads to complete).
This isn't easy to achieve. What you can try is to get access to the root ThreadGroup
(it has no parent, use Thread.currentThread().getGroup()
and then move up the chain). All threads are children of this group (or a subgroup of it).
So you can iterate over this tree until only daemon-threads are left:
int maxWait = 100;
while(countNonDaemonThreads() > 0 && --maxWait > 0) {
Thread.sleep(100);
}
This should work, but I haven't tested it. Note that you need to be careful with code in the shutdown thread; it must not block and you must somehow handle all the errors or the VM might be unable to terminate properly.
EDIT The code in The code in java.lang.Shutdown
is single-threaded, so if one of the shutdown hooks blocks, the whole VM hangs.
Now to your questions:
The VM terminates when halt()
is being called. That's the last thing that Terminate.run()
does, so yes, the VM should really terminate at the end of run()
. I don't even think run()
will ever return. There might be bugs and native code which can get in the way but that's how it's supposed to be.
A good practice is to use thread pools to do your work and wait for them to finish. Shutdown hooks are kind of a last resort. Since you can't really influence order and you can't be sure whether non-daemon threads might be still around, they are brittle for "last turns lights off" kind of work.
Using thread pools, you can have several independent of them, you can cleanly define how to shut the pools down and how to wait for them to finish. And most importantly, you can build your threads in such a way that you can abort them. When you're in a shutdown hook and one non-daemon thread refuses to die, what are you going to do? With a thread pool, you'll know the kind of thread which could be inside and by that the risk to simply terminate it.
Upvotes: 2
Reputation: 533500
Am I correct that shutdown completes when shutdown hook's thread's run method completes? What is a good practice way to perform the shutdown, waiting for my actual shutdown tasks to complete?
Make your shutdown thread non-daemons
If this is not enough you have a bug in your code. You can prove to yourself that a shut down hook which doesn't exit won't be killed of early.
Upvotes: 1