From 9a79fa64c6298998d04a5ae6d699222a93cd0cb8 Mon Sep 17 00:00:00 2001
From: Kirill Smelkov <kirr@nexedi.com>
Date: Fri, 24 Dec 2021 13:55:08 +0300
Subject: [PATCH] [py27] subprocess: Use /proc/self/fd/ to know opened file
 descriptors

... to avoid O(MAXFD) slowdown on closefds=True.

This is semantic backport of what Python3 does.
---
 Lib/subprocess.py | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/Lib/subprocess.py b/Lib/subprocess.py
index 1f2da0ffbe8..300557220ac 100644
--- a/Lib/subprocess.py
+++ b/Lib/subprocess.py
@@ -869,7 +869,28 @@ def pipe_cloexec(self):
 
 
         def _close_fds(self, but):
-            if hasattr(os, 'closerange'):
+            # try to retrieve list of opened file descriptors to avoid being slow on large MAXFD
+            # https://www.erp5.com/project_section/vifib/forum/python2--subprocess.Popen-is-slow-when-close_fds-True-and-nofile-ulimit-is-high-PO01sREVXn
+            # https://bugs.python.org/issue8052
+            # https://github.com/python/cpython/commit/8facece99a59
+            fdv = None
+            try:
+                fdv = os.listdir('/proc/self/fd')
+            except OSError as e:
+                if e.errno != errno.ENOENT:
+                    raise
+            if fdv is not None:
+                for fd_ in fdv:
+                    fd = int(fd_)
+                    if (0 <= fd <= 2) or fd == but:
+                        continue
+                    try:
+                        os.close(fd)
+                    except Exception: # e.g. not KeyboardInterrupt nor SystemExit
+                        pass
+
+            # fallback to closing all file descriptors in 3..MAXFD range
+            elif hasattr(os, 'closerange'):
                 os.closerange(3, but)
                 os.closerange(but + 1, MAXFD)
             else:
-- 
2.30.2

