Skip to content

Add a signal-timeout delivery hook - #204

Open
tamird wants to merge 1 commit into
pytest-dev:mainfrom
tamird:tamird/signal-expiry-hook
Open

Add a signal-timeout delivery hook#204
tamird wants to merge 1 commit into
pytest-dev:mainfrom
tamird:tamird/signal-expiry-hook

Conversation

@tamird

@tamird tamird commented Aug 20, 2026

Copy link
Copy Markdown

A SIGALRM failure can be consumed by an event-loop callback before it reaches the test runner, as reported in #113. The timer hooks added in #117 allow an async plugin to replace the complete timer, but not just the delivery of its failure.

Add an item-scoped pytest_timeout_expired hook after debugger checks and stack diagnostics. A plugin can accept the existing failure for delivery at its own execution boundary; otherwise pytest-timeout raises the same exception immediately. The timer and thread method retain their existing behavior. Claiming cooperative delivery does not guarantee termination.

The paired pytest-asyncio implementation 1 uses this hook to queue cancellation without raising into asyncio's task scheduler. Its cooperative behavior is explicitly opt-in.

Prepared with Codex assistance.

A failure raised by SIGALRM can be consumed by an event-loop
callback before it reaches the test runner [1]. Existing setup and
cancellation hooks require replacing the timer implementation to
change how its failure is delivered.

Add an item-scoped expiry hook after debugger checks and stack
diagnostics. A plugin can accept the existing failure for delivery at
its own execution boundary; otherwise the same exception is raised
immediately. Keep timer policy and the thread method unchanged.
Claiming cooperative delivery does not guarantee termination.

[1]: pytest-dev#113
tamird added a commit to tamird/pytest-asyncio that referenced this pull request Aug 20, 2026
A signal timeout can interrupt asyncio while it schedules a task's
next step, leaving the task pending without a continuation [1].
Catching the resulting pytest failure and cancelling that task cannot
reliably recover it.

Add opt-in cooperative delivery through pytest-timeout's proposed
expiry hook [2]. Queue cancellation without raising into the scheduler,
then report the supplied failure at the owned runner boundary. Preserve
external cancellation, process-control exceptions, and the interrupted
await's traceback. Stop final runner shutdown separately when it times
out; ordinary shared-runner invocations remain reusable.

Keep timer selection, deadlines, debugger handling, and diagnostics in
pytest-timeout. Existing signal behavior remains the default.
Cooperative cancellation cannot stop blocking or cancellation-resistant
code, so the thread method remains the hard process-stop option. Final
runner shutdown may leave resource cleanup incomplete.

Pin the producer prerequisite in a dedicated integration environment
until its hook is released. Collect coverage from the isolated pytest
processes and map installed-wheel paths back to the source tree.
Require Coverage.py 7.10.3 for its subprocess-directory fixes [3].

[1]: pytest-dev/pytest-timeout#113
[2]: pytest-dev/pytest-timeout#204
[3]: https://coverage.readthedocs.io/en/7.10.3/changes.html
tamird added a commit to tamird/pytest-asyncio that referenced this pull request Aug 20, 2026
A signal timeout can interrupt asyncio while it schedules a task's
next step, leaving the task pending without a continuation [1].
Catching the resulting pytest failure and cancelling that task cannot
reliably recover it.

Add opt-in cooperative delivery through pytest-timeout's proposed
expiry hook [2]. Queue cancellation without raising into the scheduler,
then report the supplied failure at the owned runner boundary. Preserve
external cancellation, process-control exceptions, and the interrupted
await's traceback. Stop final runner shutdown separately when it times
out; ordinary shared-runner invocations remain reusable.

Keep timer selection, deadlines, debugger handling, and diagnostics in
pytest-timeout. Existing signal behavior remains the default.
Cooperative cancellation cannot stop blocking or cancellation-resistant
code, so the thread method remains the hard process-stop option. Final
runner shutdown may leave resource cleanup incomplete.

Pin the producer prerequisite in a dedicated integration environment
until its hook is released. Collect coverage from the isolated pytest
processes and map installed-wheel paths back to the source tree.
Require Coverage.py 7.10.3 for its subprocess-directory fixes [3].

[1]: pytest-dev/pytest-timeout#113
[2]: pytest-dev/pytest-timeout#204
[3]: https://coverage.readthedocs.io/en/7.10.3/changes.html
@tamird
tamird marked this pull request as ready for review August 20, 2026 01:54
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.

1 participant