Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hook before timeout exception is started by calling interrupt() #2938

Closed
frankbenoit opened this issue Jun 7, 2022 · 10 comments · Fixed by #3431
Closed

Hook before timeout exception is started by calling interrupt() #2938

frankbenoit opened this issue Jun 7, 2022 · 10 comments · Fixed by #3431

Comments

@frankbenoit
Copy link

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
@khmarbaise
Copy link

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. ?

@frankbenoit
Copy link
Author

frankbenoit commented Jul 30, 2022

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

@axelfontaine
Copy link

+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.

@marcphilipp
Copy link
Member

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
Copy link
Member

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

@frankbenoit
Copy link
Author

@marcphilipp no, sorry, not at the moment

AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Aug 19, 2023
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.extensions.preinterruptcallback.default.enabled = true

Issue: junit-team#2938
@AndreasTu
Copy link
Contributor

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

AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Aug 19, 2023
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.extensions.preinterruptcallback.default.enabled = true

Issue: junit-team#2938
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Aug 19, 2023
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.extensions.preinterruptcallback.default.enabled = true

Issue: junit-team#2938
@PhilipIngham
Copy link

@AndreasTu Hey, are you continuing working on this? If not, would you be alright with me picking it up and finishing off that PR, as there are a few conflicts on the PR from being dormant for a while.

@marcphilipp marcphilipp linked a pull request Jun 21, 2024 that will close this issue
6 tasks
@AndreasTu
Copy link
Contributor

@PhilipIngham I am still waiting on feedback or a review of my code by anyone :)

@PhilipIngham
Copy link

I'm happy with those changes :)

AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 15, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.err.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 15, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 17, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938

Co-authored-by: Marc Philipp <[email protected]>
@marcphilipp marcphilipp added this to the 5.12 M1 milestone Oct 17, 2024
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 17, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938

Co-authored-by: Marc Philipp <[email protected]>
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 21, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938

Co-authored-by: Marc Philipp <[email protected]>
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 21, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938

Co-authored-by: Marc Philipp <[email protected]>
AndreasTu added a commit to AndreasTu/junit5 that referenced this issue Oct 25, 2024
Added PreInterruptCallback extension to allow to hook into the
@timeout extension before the executing Thread is interrupted.

The default implementation of PreInterruptCallback will simply print
the stacks of all Thread to System.out.
It is disabled by default and must be enabled with:
junit.jupiter.execution.timeout.threaddump.enabled = true

Issue: junit-team#2938

Co-authored-by: Marc Philipp <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment