Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion wifite/util/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,33 @@ def __exit__(self, exc_type, exc_val, exc_tb):
self.cleanup()

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
Comment on lines 214 to +223

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.
if hasattr(self, 'pid') and self.pid:
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.
except Exception:
pass
for stream in (self.pid.stdin, self.pid.stdout, self.pid.stderr):
if stream:
try:
stream.close()
except Exception:
pass
for fh in getattr(self, '_devnull_handles', []):
try:
fh.close()
except Exception:
pass
except Exception:
pass

Expand Down
Loading