Skip to content

fix: prevent deadlock when Actor.exit() is called from an event listener#1061

Open
vdusek wants to merge 3 commits into
masterfrom
worktree-fix-b4
Open

fix: prevent deadlock when Actor.exit() is called from an event listener#1061
vdusek wants to merge 3 commits into
masterfrom
worktree-fix-b4

Conversation

@vdusek

@vdusek vdusek commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Actor.exit() / Actor.fail() called from within an event listener (e.g. an ABORTING handler cleaning up on a graceful abort) deadlocked into a RecursionError and never completed cleanup. The cleanup path waits for all tracked event-listener tasks to finish - including the listener task that called exit() - so it awaits its own await-chain; when that wait times out the cancellation recurses into itself. As a result Actor._active stayed True, the event and charging managers never shut down, state was never persisted, and sys.exit never ran - the run only died when force-killed.

The fix detaches the caller's own task from the event manager's listener-task set for the duration of cleanup and restores it afterwards (so its wrapper can still deregister it), so neither the direct wait nor the one inside the event-manager shutdown blocks on it. It's a no-op on the normal, non-listener exit path, and mirrors the workaround reboot() already uses for this same deadlock class.

The regression test registers an ABORTING listener that calls Actor.exit() and asserts the exit completes, the event manager shuts down, and no RecursionError is logged; it fails on the old code and passes with the fix.

✍️ Drafted by Claude Code

@vdusek vdusek added adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. labels Jul 21, 2026
@vdusek vdusek self-assigned this Jul 21, 2026
@github-actions github-actions Bot added this to the 145th sprint - Tooling team milestone Jul 21, 2026
@github-actions github-actions Bot added the tested Temporary label used only programatically for some analytics. label Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.95%. Comparing base (58d6da1) to head (b2a2255).

Files with missing lines Patch % Lines
src/apify/_actor.py 88.88% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1061      +/-   ##
==========================================
+ Coverage   91.89%   91.95%   +0.06%     
==========================================
  Files          51       51              
  Lines        3232     3245      +13     
==========================================
+ Hits         2970     2984      +14     
+ Misses        262      261       -1     
Flag Coverage Δ
e2e 35.28% <16.66%> (-0.05%) ⬇️
integration 57.22% <77.77%> (+0.14%) ⬆️
unit 83.32% <88.88%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vdusek
vdusek requested a review from Pijukatel July 21, 2026 11:06
@vdusek
vdusek marked this pull request as ready for review July 21, 2026 11:06
Comment thread src/apify/_actor.py
@vdusek

vdusek commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

maybe we can close this in favor of apify/crawlee-python#2088

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

Labels

adhoc Ad-hoc unplanned task added during the sprint. t-tooling Issues with this label are in the ownership of the tooling team. tested Temporary label used only programatically for some analytics.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants