Skip to content

fix: prevent pytest hanging by avoiding threading.Lock in Process.__d…#446

Merged
kimocoder merged 1 commit into
masterfrom
claude/fix-pytest-hanging-c9xQe
Mar 6, 2026
Merged

fix: prevent pytest hanging by avoiding threading.Lock in Process.__d…#446
kimocoder merged 1 commit into
masterfrom
claude/fix-pytest-hanging-c9xQe

Conversation

@kimocoder

Copy link
Copy Markdown
Owner

…el__

During interpreter shutdown, Python tears down module globals including the threading module. When Process.del called cleanup() which called ProcessManager.unregister_process(), it tried to acquire a threading.Lock. This caused an infinite process-restart loop, making pytest tests/ hang indefinitely after test completion.

The fix replaces the full cleanup() call in del with lightweight inline cleanup that only kills subprocesses and closes file descriptors, skipping the lock-dependent ProcessManager.unregister_process() call. The atexit handler already handles bulk process cleanup at exit.

https://claude.ai/code/session_017pnDqUB249KbWHseNGTS16

…el__

During interpreter shutdown, Python tears down module globals including
the threading module. When Process.__del__ called cleanup() which called
ProcessManager.unregister_process(), it tried to acquire a threading.Lock.
This caused an infinite process-restart loop, making pytest tests/ hang
indefinitely after test completion.

The fix replaces the full cleanup() call in __del__ with lightweight
inline cleanup that only kills subprocesses and closes file descriptors,
skipping the lock-dependent ProcessManager.unregister_process() call.
The atexit handler already handles bulk process cleanup at exit.

https://claude.ai/code/session_017pnDqUB249KbWHseNGTS16
Copilot AI review requested due to automatic review settings March 6, 2026 00:02
@kimocoder kimocoder merged commit 85a390f into master Mar 6, 2026
10 of 12 checks passed

Copilot AI 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.

Pull request overview

Fixes pytest hangs during interpreter shutdown by preventing Process.__del__ from taking the ProcessManager lock (which can be unsafe once threading globals are torn down), while still performing best-effort subprocess/FD cleanup.

Changes:

  • Replace __del__’s full cleanup() call with inline, lock-free cleanup (kill subprocess + close streams/devnull handles).
  • Document why ProcessManager.unregister_process() is intentionally skipped in __del__ (atexit handler does bulk cleanup).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread wifite/util/process.py
try:
if self.pid.poll() is None:
self.pid.kill()
self.pid.wait()

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

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

In del, calling self.pid.wait() can block indefinitely if the subprocess doesn't exit cleanly (even after kill()), which risks reintroducing the “pytest hangs at shutdown” failure mode. Consider avoiding a blocking wait in the destructor (or use a short timeout and swallow subprocess.TimeoutExpired) so interpreter finalization can’t hang here.

Suggested change
self.pid.wait()
try:
# Use a short, bounded wait to avoid hanging
# interpreter shutdown if the subprocess misbehaves.
self.pid.wait(timeout=0.5)
except subprocess.TimeoutExpired:
# Best-effort only: if the process still hasn't
# exited, don't block interpreter finalization.
pass

Copilot uses AI. Check for mistakes.
Comment thread wifite/util/process.py
Comment on lines 214 to +223
def __del__(self):
# During interpreter shutdown, module globals (including threading)
# may already be torn down. Acquiring a threading.Lock in that state
# can trigger an infinite-restart loop, so we only do lightweight
# cleanup here and skip ProcessManager.unregister_process entirely
# (the atexit handler already handles bulk cleanup).
try:
self.cleanup()
if getattr(self, '_cleaned_up', True):
return
# Best-effort: kill still-running subprocesses and close FDs

Copilot AI Mar 6, 2026

Copy link

Choose a reason for hiding this comment

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

This change is a regression fix for an interpreter-shutdown hang, but there’s no automated test asserting that Process.__del__ avoids calling cleanup() / ProcessManager.unregister_process() (the lock-acquiring path). Adding a small unit test that patches Process.cleanup and/or ProcessManager.unregister_process to raise and verifies __del__ doesn’t touch them would help prevent this from coming back.

Copilot uses AI. Check for mistakes.
@kimocoder kimocoder deleted the claude/fix-pytest-hanging-c9xQe branch March 6, 2026 02:56
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.

3 participants