junit5 icon indicating copy to clipboard operation
junit5 copied to clipboard

Hook before timeout exception is started by calling interrupt()

Open frankbenoit opened this issue 2 years ago • 10 comments

The problem: When having sporadic timeout exceptions, it is hard to tell from the stacktrace where the code was hanging. A debugger might not be available (sporadic, on build system) Also the stackdump of other threads might be very helpful, because the timeout might be caused by other threads activity or dead lock.

An own extension seems to be not reasonable, as the timeout control also from maven, is part of the infrastructure.

Deliverables

  • Either have a hook, that gets called before the thread.interrupt() is called in org.junit.jupiter.engine.extension.TimeoutInvocation.InterruptTask.run().
  • Or have a way to activate collecting a stackdump of all threads (just before calling interrupt() as above) and put it into the TimeoutException.
  • Or have collected stackdumps of all threads as information always in the TimeoutException

frankbenoit avatar Jun 07 '22 09:06 frankbenoit

Can you please add more information how your pom file looks like, which Maven versions, JDK version etc. you are using... Also which surefire-plugin versions etc. ?

khmarbaise avatar Jul 30 '22 11:07 khmarbaise

maven 3.8.6, surefire 2.22.2, JDK 17

To make the problem perhaps even better understandable... Given a test running code that triggers parallel workers and somehow waits for completion. If then the task (in test-thread) gets interrupted due to timeout, it might catch the InterruptedException and force the parallel workers to be closed before rethrowing. So at the time, the timeout exception can be caught from a live cycle method, it might be already too late to see the status of the parallel workers right before the interruption.

Hence I think it would be very helpful to have a hook that runs just before the thread.interrupt() call. Having the all-thread-dump from JUnit directly would be helpful, but I can also image that a screenshot or other actions can be helpful.

The location of the interrupt call is meanwhile here: https://github.com/junit-team/junit5/blob/main/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java#L79

frankbenoit avatar Jul 30 '22 11:07 frankbenoit

+1 here

This is not Maven-specific.

Something like @Timeout(value = 600, threadDump = true) would cover IDEs, Maven, Gradle and whatnot in one go.

Here is a proposed solution: https://stackoverflow.com/a/73156213/350428

Integrating this directly into JUnit itself would make it accessible to a much wider audience.

axelfontaine avatar Mar 05 '23 16:03 axelfontaine

Team decision: Add a PreInterruptCallback Extension API and a default implementation that prints a thread dump of the current JVM to System.out if a new Jupiter-specific configuration parameter is set to true.

marcphilipp avatar Jun 30 '23 10:06 marcphilipp

@frankbenoit Would you be interested in submitting a PR for this?

marcphilipp avatar Jun 30 '23 10:06 marcphilipp

@marcphilipp no, sorry, not at the moment

frankbenoit avatar Jul 01 '23 16:07 frankbenoit

@marcphilipp I have created the PR #3431, which would add the PreInterruptCallback as sketched in your comment.

AndreasTu avatar Aug 19 '23 16:08 AndreasTu