Misbehaving exit status from Hotspot

David Holmes david.holmes at oracle.com
Thu Jun 28 23:51:33 UTC 2018

On 29/06/2018 8:54 AM, Charles Oliver Nutter wrote:
> On Thu, Jun 28, 2018 at 5:34 PM, David Holmes <david.holmes at oracle.com 
> <mailto:david.holmes at oracle.com>> wrote:
>     On 29/06/2018 6:30 AM, Charles Oliver Nutter wrote:
>         But a TERM signal *did* cause the process to stop, didn't it?
>         This is not an appropriate value for the stop signal in that
>         case (indeed, garbage).
>     "stopping" a process is not "terminating" a process. ref: SIGSTOP,
>     SIGCONT ("job control").
> Ok.
>         The process *did* terminate due to receipt of a signal. The
>         number of the signal that caused the termination of the process
>         was 15, TERM. I'm still not getting something in your logic, I gue
>     Choosing to terminate in response to a signal you caught, is not the
>     same thing as being terminated (by the OS) because you did not catch
>     a signal that was sent to you.
>         Bear with me please :-) There are big gaps in the documentation
>         of this stuff online, and if what Hotspot does is "correct" and
>         "standard" I would like to know that and see the docs indicating
>         such.
>     I can't speak to the accuracy of the Mac OS documentation. I'm
>     working from the POSIX specification and looking at how Linux
>     actually behaves.
> I'm honestly trying to look at every piece of doc I can find...MacOS, 
> Linux, POSIX. I guess what I'm starting to get is that the sequence of 
> events and resulting process state from handled signals is largely 
> unspecified and up to individual programs...

Yes - handled signals are handled by programs as they see fit.

>     Obviously there is some leeway here as to how a process ultimately
>     chooses to facilitate termination. After catching a signal (any
>     signal) a process could raise a different signal that is not caught
>     and so have the OS terminate it - instead of calling exit(). That's
>     what that little code snipped your report links to shows - it
>     catches TERM, does what it needs to do, then removes the handler for
>     TERM, raises TERM against itself and so commits process suicide. It
>     gives the illusion that it was terminated by the initial TERM
>     signal, but it wasn't, it was terminated by the second, uncaught,
>     TERM signal.
> I think that's actually what I want, though, and I'm not entirely clear 
> why Hotspot can't do that.
> If there's no handler, and you TERM an app, you get the results I've 
> shown above (the results I hope to get from TERMing Hotspot).
> If there's a handler, then you have one of two options:
> * Do whatever your handler needs to do and then re-propagate the signal 
> to the default handler to facilitate kernel-level shutdown and state 
> manipulation.

Ok - that is where I think the difference of perspective is. It isn't a 
"default handler" that needs to be chained. You don't need to 
"propagate" signals as if they were an exception you caught and now need 
to rethrow. There's no kernel-level shutdown you need to facilitate.

Signals are just a communication mechanism to inform the process about 
something that is happening - it might be a physical something (you just 
had a page fault!) or a logical something (you've been sent a request to 
terminate). But as described in Section "2.4.3 Signal Actions" here:


there are default actions associated with each signal, if a process 
doesn't provide an explicit action.

"If the default action is to terminate the process abnormally, the 
process is terminated as if by a call to _exit(), except that the status 
made available to wait(), waitid(), and waitpid() indicates abnormal 
termination by the signal."

So if you have no handler for TERM you will be terminated abnormally and 
its reported via WIF* (WIFEXITED will be false, and WIFSIGNALED will be 
true). If you catch the TERM signal and later choose to do a normal 
termination then that's up to you.

To be clear, I think the libc advise on this topic is just wrong-headed:


"Such a handler should end by specifying the default action for the 
signal that happened and then reraising it; this will cause the program 
to terminate with that signal, as if it had not had a handler."

It's not even self-consistent because it states this for the 
"termination signals" but when caught some of these signals 
intentionally do not trigger termination. So following that advice for 
SIGQUIT would be completely wrong for the JVM!

> * Do whatever your handler needs to do and NOT re-propagate the signal 
> to the default handler. Encode your own app-specific exit code.
> Why couldn't Hotspot:
> * Save the fact that termination was initiated by a TERM signal.
> * Do all appropriate shutdown for the JVM.
> * Prepare to exit process, see that shutdown was initiated by TERM, and 
> re-propagate TERM to the system handler rather than doing the "clean" 
> exit().
> Command-line exit code would be right, WEXITSTATUS would indicate that 
> this was signal-initiated shutdown of the process,

WEXITSTATUS only has meaning if the process was _not_ terminated by a 
signal. If you re-raise (I won't say propagate) the signal then you 

> and the remaining 
> macros would indicate why. Everyone's happy!

Umm no, everyone is not happy! The appearance of an abnormal termination 
would suggest there was no orderly shutdown of the VM, when there was. 
An abnormal termination suggests to a sysadmin that something has gone 
badly wrong, when in this case it hasn't.

The way to look at this from a waitpid() perspective is this:

- first check if WIFEXITED
- if true then the JVM terminated of its own choice, so now check 
WIFEXITSTATUS to see why it chose to terminate

The 143 (being "signal number" + 128) reflects that it was responding to 
a shutdown request made via a TERM signal.

> This also explains the difference between CRuby, which I'm trying to 
> (a.k.a. forced to) emulate. CRuby *does* repropagate the signal after 
> doing its VM cleanup, and so the macros reflect a shutdown initiated by 
> an external signal.

That's their choice but I don't agree with it in general.

>     As I said there is no standard that says what happens for caught
>     signals, only what happens for uncaught signals - and uncaught
>     signals are all that counts for waitpid and WI* macros on exit
>     status. And you have to recognize that the macros are only valid
>     under specific conditions - no point reading WIFEXITSTATUS if the
>     process was WIFSIGNALED; no point reading WTERMSIG if the process
>     was WIFEXITED.
>     It is up to an individual program to decide both what communication
>     mechanisms can lead to its termination (signals, poison-packets, GUI
>     events) and what exit status it reports in response to them. For the
>     JVM the exit status reflects how the shutdown request was
>     originated, so for signals it uses the "standard" convention of
>     "signal number" + 128. This is useful and necessary information for
>     a sysadmin.
> The ultimate answer may be "it's legal to do this, and Hotspot does it, 
> so Hotspot will continue to do it" but I'd really like to understand 
> *why* the signal doesn't get repropagated. It seems to me there's no 
> reason not to, since the command-line exit code would still be the same. 
> It would just make the other macros reflect the fact that the process 
> shut down in response to a signal (and yes, I know it's not an 
> *unhandled* signal...but why can't we make those macros work anyway?) 

To me you're trying to distort the meaning of those macros. They exist 
to distinguish between normal and abnormal terminations of a process. 
Where by definition uncaught signals (on a case by case basis) lead to 
abnormal termination as I quoted from POSIX.

> Most examples I've seen (of TERM-hooking shutdown) *do* repropagate, 
> presumably for the reasons I've raised in this thread.

I can't speak to other programs of an equivalent nature to the JVM. I'd 
be interested to know what other language runtimes like Self and 
Smalltalk did in this area. Or how a 30 year old UNIX programming 
textbook instructs you in this area. :)

But the JVM is not doing anything wrong and after 20+ years it's not 
going to change without a very good reason.

> Thanks for your patience!



> - Charlie

More information about the hotspot-runtime-dev mailing list