| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 82b7065 commit 3cfd229
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -368,8 +368,12 @@ def _terminate(self) -> None: | |||
| 368 | 368 | status = proc.wait() # Ensure the process goes away. | |
| 369 | 369 | ||
| 370 | 370 | 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) | ||
| 373 | 377 | # END exception handling | |
| 374 | 378 | ||
| 375 | 379 | def __del__(self) -> None: | |
| Original file line number | Diff line number | Diff 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 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments