Skip to content

Commit dae9b25

Browse files
committed
fix: ignore AutoInterrupt terminate errors during shutdown
1 parent 22e0b52 commit dae9b25

File tree

2 files changed

+41
-2
lines changed

2 files changed

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

0 commit comments

Comments
 (0)