X Tutup
Skip to content

Commit e23c548

Browse files
authored
Merge pull request #2105 from lweyrich1/fix-autointerrupt-shutdown-guard
fix: guard AutoInterrupt terminate during interpreter shutdown
2 parents 82b7065 + 357aad1 commit e23c548

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

git/cmd.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -368,8 +368,12 @@ def _terminate(self) -> None:
368368
status = proc.wait() # Ensure the process goes away.
369369

370370
self.status = self._status_code_if_terminate or status
371-
except OSError as ex:
372-
_logger.info("Ignored error after process had died: %r", ex)
371+
except (OSError, AttributeError) as ex:
372+
# On interpreter shutdown (notably on Windows), parts of the stdlib used by
373+
# subprocess can already be torn down (e.g. `subprocess._winapi` becomes None),
374+
# which can cause AttributeError during terminate(). In that case, we prefer
375+
# to silently ignore to avoid noisy "Exception ignored in: __del__" messages.
376+
_logger.info("Ignored error while terminating process: %r", ex)
373377
# END exception handling
374378

375379
def __del__(self) -> None:

test/test_autointerrupt.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
from git.cmd import Git
2+
3+
4+
class _DummyProc:
5+
"""Minimal stand-in for subprocess.Popen used to exercise AutoInterrupt.
6+
7+
We deliberately raise AttributeError from terminate() to simulate interpreter
8+
shutdown on Windows where subprocess internals (e.g. subprocess._winapi) may
9+
already be torn down.
10+
"""
11+
12+
stdin = None
13+
stdout = None
14+
stderr = None
15+
16+
def poll(self):
17+
return None
18+
19+
def terminate(self):
20+
raise AttributeError("TerminateProcess")
21+
22+
def wait(self): # pragma: no cover - should not be reached in this test
23+
raise AssertionError("wait() should not be called if terminate() fails")
24+
25+
26+
def test_autointerrupt_terminate_ignores_attributeerror():
27+
ai = Git.AutoInterrupt(_DummyProc(), args=["git", "rev-list"])
28+
29+
# Should not raise, even if terminate() triggers AttributeError.
30+
ai._terminate()
31+
32+
# Ensure the reference is cleared to avoid repeated attempts.
33+
assert ai.proc is None

0 commit comments

Comments
 (0)
X Tutup