From 2e96ea757a45a4e5c7de9075d6a75f0085072a27 Mon Sep 17 00:00:00 2001 From: SJ <76181208+imaginary-person@users.noreply.github.com> Date: Fri, 5 Feb 2021 23:33:52 -0600 Subject: [PATCH 1/3] Do not add duplicate FDs in duplicate_for_child() While spawning, if the code built on top of python's multiprocessing module calls DupFd (in /Lib/multiprocessing/reduction.py) multiple times on the same File descriptor by mistake, then it ends up invoking duplicate_for_child(fd)) of the class Popen, which, in turn, adds a duplicate FD to a list. This list is then used in spawnv_passfds() in multiprocessing/util.py, which uses that list as an argument in a call of _posixsubprocess.fork_exec(). In Modules/_posixsubprocess.c, checks exist to ensure that all the FDs in the list are unique, positive, and in a sorted order. If duplicate entries are found, a 'ValueError: bad value(s) in fds_to_keep' exception is raised, and the execution is terminated because this exception is not handled by Python. Even if it were, a developer can't change the aforementioned FD list in Python without breaking modularity. It's better to let developers get away with calling DupFd (in /Lib/multiprocessing/reduction.py) by not accepting duplicate entries in the first place, so that spawning a process can be successful. --- Lib/multiprocessing/popen_spawn_posix.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/multiprocessing/popen_spawn_posix.py b/Lib/multiprocessing/popen_spawn_posix.py index 24b8634523e5f2..c3c96b52675cd0 100644 --- a/Lib/multiprocessing/popen_spawn_posix.py +++ b/Lib/multiprocessing/popen_spawn_posix.py @@ -32,7 +32,8 @@ def __init__(self, process_obj): super().__init__(process_obj) def duplicate_for_child(self, fd): - self._fds.append(fd) + if fd not in self._fds: + self._fds.append(fd) return fd def _launch(self, process_obj): From f06f482ee906a44c8967672b99da309f9ee7abe4 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Sat, 6 Feb 2021 06:43:53 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../NEWS.d/next/Library/2021-02-06-06-43-52.bpo-43142.Gt_6Yb.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Library/2021-02-06-06-43-52.bpo-43142.Gt_6Yb.rst diff --git a/Misc/NEWS.d/next/Library/2021-02-06-06-43-52.bpo-43142.Gt_6Yb.rst b/Misc/NEWS.d/next/Library/2021-02-06-06-43-52.bpo-43142.Gt_6Yb.rst new file mode 100644 index 00000000000000..87ec85faa69209 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2021-02-06-06-43-52.bpo-43142.Gt_6Yb.rst @@ -0,0 +1 @@ +Do not add duplicate FDs to list in duplicate_for_child() in order to avoid ValueError: bad value(s) in fds_to_keep \ No newline at end of file From 31a801be035c0a5dd57791657c68e06496cc7821 Mon Sep 17 00:00:00 2001 From: SJ <76181208+imaginary-person@users.noreply.github.com> Date: Sat, 6 Feb 2021 01:22:00 -0600 Subject: [PATCH 3/3] Add comment to trigger CI All tests except the news item addition had passed the first time around, so need to re-run CI. --- Lib/multiprocessing/popen_spawn_posix.py | 1 + 1 file changed, 1 insertion(+) diff --git a/Lib/multiprocessing/popen_spawn_posix.py b/Lib/multiprocessing/popen_spawn_posix.py index c3c96b52675cd0..7c0377035baa6a 100644 --- a/Lib/multiprocessing/popen_spawn_posix.py +++ b/Lib/multiprocessing/popen_spawn_posix.py @@ -32,6 +32,7 @@ def __init__(self, process_obj): super().__init__(process_obj) def duplicate_for_child(self, fd): + # duplicates in self._fds would later lead to a ValueError if fd not in self._fds: self._fds.append(fd) return fd