RFR: 8289610: Degrade Thread.stop [v4]

Stuart Marks smarks at openjdk.org
Tue Sep 20 16:32:54 UTC 2022


On Tue, 20 Sep 2022 06:00:14 GMT, Alan Bateman <alanb at openjdk.org> wrote:

>> src/java.base/share/classes/java/io/FilterOutputStream.java line 195:
>> 
>>> 193:                    // evaluate possible precedence of flushException over closeException
>>> 194:                    if ((flushException instanceof ThreadDeath) &&
>>> 195:                        !(closeException instanceof ThreadDeath)) {
>> 
>> If the ThreadDeath originates from the debugger then this is now a change in behaviour.
>
>> Good to see this finally become non-functional but as long as the debugger/JVMTI can trigger throwing an async ThreadDeath then I have to question the potential change in behaviour introduced by removing all the `catch (ThreadDeath td)` logic in various places.
> 
> I've gone through this a few times too and concluded it would be better to remove these untestable code paths. The debugger scenario is more like what used to be Thread.stop(Throwable). It can be used to throw any exception or error, e.g. ask the debugger to throw IllegalArgumentException or SQLException when I'm at this breakpoint so I can see how the code behaves. Yes, the user could ask the debugger to throw java.lang.ThreadDeath when prompted but it's not really interesting now because code won't get this error outside of a debugger. We could leave the special handing but we have no way to test is and we'll need to the remove the special handling when TD is removed.  As a general point, the special casing of TD is a bit inconsistent and more likely to be seen in older code rather newer code. A static analysis of 24M classes found very few usages in 3rd party libraries.

I agree with Alan on this. First, use and handling of `ThreadDeath` is quite rare; see my [analysis](https://bugs.openjdk.org/browse/JDK-8289610?focusedCommentId=14523723&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-14523723) of the corpus search results in the bug report. Second, while this does change the behavior in the debugger case, I'm hard-pressed to see how anybody is _relying_ on such behavior. And maybe somebody somewhere is indeed relying on this behavior, but it doesn't seem to me this behavior is guaranteed by any specifications.

A more likely way that programs could observe changes in `ThreadDeath` handling occurs when programs throw `ThreadDeath` explicitly, that is, not using `Thread.stop`. This does seem to occur infrequently "in the wild" (we'll fix the jshell case). The point of throwing `ThreadDeath` explicitly is to take advantage of special-case handling of `ThreadDeath` that might occur higher in the call stack. Such special-casing was at one time an accepted exception handing idiom, but it's essentially disused. I don't think the JDK needs to continue to support this old idiom.

-------------

PR: https://git.openjdk.org/jdk/pull/10230


More information about the serviceability-dev mailing list