I'm porting a project to Python3 and I'm running into a unexpected error on Windows:
Basically on Python 3.6 on Windows, each time a process is being created with subprocess, I have this exception:
d:\temp\backpack\venv\myvenv_py3.6\lib\site-packages\git\cmd.py:1011: in _call_process
return self.execute(call, **exec_kwargs)
d:\temp\backpack\venv\myvenv_py3.6\lib\site-packages\git\cmd.py:732: in execute
**subprocess_kwargs
D:\temp\cpython-3.6.3\Lib\subprocess.py:611: in __init__
_cleanup()
D:\temp\cpython-3.6.3\Lib\subprocess.py:220: in _cleanup
res = inst._internal_poll(_deadstate=sys.maxsize)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <subprocess.Popen object at 0x0000000004FD53C8>
_deadstate = 9223372036854775807
_WaitForSingleObject = <built-in function WaitForSingleObject>
_WAIT_OBJECT_0 = 0, _GetExitCodeProcess = <built-in function GetExitCodeProcess>
def _internal_poll(self, _deadstate=None,
_WaitForSingleObject=_winapi.WaitForSingleObject,
_WAIT_OBJECT_0=_winapi.WAIT_OBJECT_0,
_GetExitCodeProcess=_winapi.GetExitCodeProcess):
"""Check if child process has terminated. Returns returncode
attribute.
This method is called by __del__, so it can only refer to objects
in its local scope.
"""
_log.debug('proc._internal_poll self.pid=%s self._handle=%s self.returncode=%s self=%s', self.pid, self._handle, self.returncode, self)
if self.returncode is None:
> if _WaitForSingleObject(self._handle, 0) == _WAIT_OBJECT_0:
E OSError: [WinError 6] The handle is invalid
D:\temp\cpython-3.6.3\Lib\subprocess.py:1051: OSError
It doesn't matter where the subprocess
call is being created from (in this project it's a lot from the GitPython
package and from plumbum
).
This execution occurs under this umbrella: build script
which invokes venv/Scripts/coverage run -m pytest -v tests/
. But I've also tried pytest-cov
with venv/Scripts/pytest --cov=mypackage --cov-config .coveragerc - tests/
In terms of reproduction:
<build script>
invokes venv/Scripts/coverage run -m pytest
]coverage run -m pytest
is invoked directly from the venvpytest
is invoked directly from the virtualenv<build script>
is invoked, or if coverage
or pytest
are invoked directly from the venvThe only clue that I've got so far is from this StackOverflow thread: https://stackoverflow.com/a/43975118
and to be more precise, it's the comments from the first accepted answer that point to something useful related to the _cleanup
method from the subprocess
module.
A similar error is common when running via pythonw.exe. Prior to Windows 8, a pythonw.exe process has console handle values in its standard handles, but they're invalid since there's no attached console. subprocess raises an error when it tries to call DuplicateHandle on the invalid handle.
2) ignore EBADF (OSError: [WinError 6] The handle is invalid) in terminate () and probably some other methods ERROR_INVALID_HANDLE should not be ignored. terminate () is doing the right thing by not masking ERROR_INVALID_HANDLE.
So yeah, it's a severe bug in an application. An application should not close the wrong handle by mistake :-) Thanks for the explanation. So it would be "nice" to backport the change to reduce the impact of such application bug, but it's not really a bug in Python itself. Python cannot fully protect developers for such class of bugs.
Here's my current understanding: def __del__ (self, _maxsize=sys.maxsize, _warn=warnings.warn): if not self._child_created or self.returncode is not None: return # In Unix, not reading the subprocess exit status creates a zombie # process, which is only destroyed at the parent Python process exit.
After a bit of pause, I quickly found the reason behind this.
It was because of the GitPython
usage in the project which didn't call git.Repo.close()
or used git.Repo
as a context manager.
There is a warning about this on GitPython
's readme.
It was helpful to add logging in subprocess
's _internal_poll
method to know which process (args
) is the culprit. For GitPython
it was git cat-file
...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With