bpo-38982: Fix asyncio PidfdChildWatcher on waitpid() error (GH-17477)

If waitpid() is called elsewhere, waitpid() call fails with
ChildProcessError: use return code 255 in this case, and log a
warning. It ensure that the pidfd file descriptor is closed if this
error occurs.
This commit is contained in:
Victor Stinner 2019-12-06 16:32:41 +01:00 committed by GitHub
parent b64334cb93
commit e76ee1a72b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 18 additions and 2 deletions

View File

@ -930,9 +930,20 @@ class PidfdChildWatcher(AbstractChildWatcher):
def _do_wait(self, pid):
pidfd, callback, args = self._callbacks.pop(pid)
self._loop._remove_reader(pidfd)
_, status = os.waitpid(pid, 0)
try:
_, status = os.waitpid(pid, 0)
except ChildProcessError:
# The child process is already reaped
# (may happen if waitpid() is called elsewhere).
returncode = 255
logger.warning(
"child process pid %d exit status already read: "
" will report returncode 255",
pid)
else:
returncode = _compute_returncode(status)
os.close(pidfd)
returncode = _compute_returncode(status)
callback(pid, returncode, *args)
def remove_child_handler(self, pid):

View File

@ -0,0 +1,5 @@
Fix asyncio ``PidfdChildWatcher``: handle ``waitpid()`` error. If
``waitpid()`` is called elsewhere, ``waitpid()`` call fails with
:exc:`ChildProcessError`: use return code 255 in this case, and log a
warning. It ensures that the pidfd file descriptor is closed if this error
occurs.