-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
bpo-37410: subprocess closes the process handle when done #14391
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
On Windows, subprocess.Popen now closes the process handle when the process completes. Previously, it was only closed when the Popen object was destroyed.
See also https://bugs.python.org/issue37380 |
cc @gpshead |
* Add _set_returncode() to the Windows implementation * Rename _handle_exitstatus() to _set_returncode() in the Unix implementation
Two newlines between methods.
Oh, a test now fails on Windows:
It seems like _wait() is not longer thread-safe with my change... but I'm surprised that it was thread-safe before my change. The Unix implementation uses a lock to make _wait() thread-safe. Extract:
Maybe the Windows implementation should also use a lock? The failing test comes from https://bugs.python.org/issue21291 |
Before we could rely on def _wait(self, timeout):
"""Internal implementation of wait() on Windows."""
if self.returncode is not None:
return self.returncode
if timeout is None:
self._status_lock.acquire()
else:
if timeout < 0:
# Disallow the -1 default timeout value of acquire.
raise ValueError('timeout value must be positive')
endtime = _time() + timeout
if not self._status_lock.acquire(timeout=timeout):
raise TimeoutExpired(self.args, timeout)
try:
if self.returncode is None:
if timeout is None:
remaining_ms = _winapi.INFINITE
else:
remaining = endtime - _time() if timeout != 0 else 0
if remaining < 0:
raise TimeoutExpired(self.args, timeout)
remaining_ms = int(remaining * 1000)
# API note: returns immediately if remaining_ms is 0.
result = _winapi.WaitForSingleObject(self._handle,
remaining_ms)
if result == _winapi.WAIT_TIMEOUT:
raise TimeoutExpired(self.args, timeout)
exitcode = _winapi.GetExitCodeProcess(self._handle)
self._set_returncode(exitcode)
finally:
self._status_lock.release()
return self.returncode |
@eryksun It seems like we could re-use |
The Unix code path has the same issue and it was already been fixed. I suggest to factorize the code between Windows and Unix: reuse the same lock and the same locking code, but add sub-methods for Windows or Unix specific code. I plan to write such PR. |
The POSIX code uses a busy loop. I see no reason for that in Windows. |
My PR doesn't work: more locking is needed. Code should be shared with Unix, or copied from the Unix implementation, to add locking. I will not be available next weeks, so I prefer to close the issue. I may rewrite it properly later. |
On Windows, subprocess.Popen now closes the process handle when the
process completes. Previously, it was only closed when the Popen
object was destroyed.
https://bugs.python.org/issue37410