Skip to content

Re-arm pytest-timeout's timer for each rerun attempt - #383

Open
LouisDeconinck wants to merge 3 commits into
pytest-dev:masterfrom
LouisDeconinck:issue-99-pytest-timeout
Open

LouisDeconinck wants to merge 3 commits into
pytest-dev:masterfrom
LouisDeconinck:issue-99-pytest-timeout

Conversation

@LouisDeconinck

@LouisDeconinck LouisDeconinck commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • pytest-timeout arms a single timer around pytest_runtest_protocol; once it fired on the first attempt, every rerun ran without a timeout
  • This plugin now detects the whole-protocol timeout (func_only=False) and cancels/re-arms pytest_timeout_cancel_timer/pytest_timeout_set_timer at the start of each attempt, so each attempt gets the full configured timeout (verified: a 5s test with --timeout 1 --reruns 1 now fails in ~2s instead of passing in ~6s)
  • timeout_func_only already worked per attempt via pytest_runtest_call and is untouched

Closes #99

Test plan

  • New test asserts both attempts are timed out (bounded wall-clock + 1 failed, 1 rerun)
  • pytest-timeout added to tox test deps; test skips gracefully without it
  • Full suite green

pytest-timeout arms a single timer around pytest_runtest_protocol, so
after it fired on the first attempt every rerun ran unbounded. Detect the
plugin's whole-protocol timeout and cancel/re-arm the timer at the start
of each attempt. timeout_func_only already works per attempt via
pytest_runtest_call.

Closes pytest-dev#99.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>

@sylvesterkaczmarek sylvesterkaczmarek left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The per-attempt timeout is re-armed before runtestprotocol(), but it is not cancelled when that attempt returns. pytest-timeout only cancels its outer timer after this entire protocol hook finishes, while this plugin can still process reports and sleep for reruns_delay before the next iteration. A quick failure with --timeout 1 --reruns 1 --reruns-delay 2 can therefore time out during the backoff instead of giving the next attempt a fresh timeout. Please cancel the per-attempt timer immediately after runtestprotocol() (including exceptional paths), then re-arm it at the next attempt, and add a delay-greater-than-timeout regression.

The re-armed timer stayed armed while rerun reports were processed and
during reruns_delay, so a delay longer than the timeout could kill the
run before the next attempt got a fresh timer.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
@LouisDeconinck

Copy link
Copy Markdown
Contributor Author

Fixed in ec2934c: the per-attempt timer is now cancelled in a finally right after runtestprotocol() returns, before report processing and reruns_delay, and re-armed on the next attempt. Added a delay-greater-than-timeout regression test.

@LouisDeconinck

Copy link
Copy Markdown
Contributor Author

Fixed — the per-attempt timer is cancelled in a finally right after runtestprotocol() returns and re-armed at the next attempt, so a reruns_delay longer than the timeout no longer kills the next attempt; includes a delay-greater-than-timeout regression test (ec2934c).

sylvesterkaczmarek

This comment was marked as duplicate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Incompatible with pytest-timeout plugin

2 participants