Repository navigation
Conversation
Failing test demonstrating that execute_handler's timeout fires but doesn't free threads blocked in synchronous code (run_in_executor). CancelledError can't be delivered to a blocking sync call, and the finally block waits only 0.1s before abandoning the task.
Sync handlers previously ran directly in the event loop thread, which blocked the loop entirely and made the timeout useless. Now they run via anyio.to_thread.run_sync(abandon_on_cancel=True), so: - The event loop stays free to enforce timeouts - Cancellation is delivered to the await point (anyio's mechanism) - The worker thread may still be alive (Python can't kill threads), but the bus is no longer blocked on it For async handlers that use loop.run_in_executor internally, users should switch to anyio.to_thread.run_sync for the same cancellation benefit.
There was a problem hiding this comment.
All reported issues were addressed across 2 files
Tip: instead of fixing issues one by one fix them all with cubic
Re-trigger cubic
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Sync handlers ran directly in the event loop thread (
handler(event)), which blocked the loop entirely. If a sync handler hung (e.g. a C-level call), the timeout never fired and no other events could be processed — the entire event bus was frozen.What this changes
Sync handlers now run via
anyio.to_thread.run_sync(handler, event, abandon_on_cancel=True):awaitpoint (anyio's mechanism)Complement to #32
PR #32 (Option C) addresses the async handler path: when a handler can't be cancelled, abandon it with a warning instead of holding the global lock. This PR (Option A) addresses the sync handler path: run sync handlers in a worker thread so the timeout can actually fire. Both can be merged independently.
Fixes #31.
Summary by cubic
Run synchronous handlers with
anyio.to_thread.run_syncso handler timeouts take effect and the event loop remains responsive. Previously, sync handlers ran on the event loop thread, which froze the bus when a handler blocked and prevented timeouts from firing.anyio.fail_afterand awaitanyio.to_thread.run_sync(..., abandon_on_cancel=True); otherwise awaitrun_syncwithout a deadline.tests/test_handler_timeout_zombie_thread.pyto verify a blocking sync handler no longer blocks subsequent events after timeout.Written for commit 9c37fa9. Summary will update on new commits.