View | Details | Raw Unified | Return to bug 250322
Collapse All | Expand All

(-)lang/python36/Makefile (-1 / +1 lines)
Lines 3-9 Link Here
3
3
4
PORTNAME=	python
4
PORTNAME=	python
5
PORTVERSION=	${PYTHON_PORTVERSION}
5
PORTVERSION=	${PYTHON_PORTVERSION}
6
PORTREVISION=	1
6
PORTREVISION=	2
7
CATEGORIES=	lang python
7
CATEGORIES=	lang python
8
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
9
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
9
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
(-)lang/python36/files/patch-Modules___posixsubprocess.c (-25 lines)
Lines 1-25 Link Here
1
# Add closefrom(2) support
2
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274
3
# https://bugs.python.org/issue38061
4
# TODO: Upstream
5
6
--- Modules/_posixsubprocess.c.orig	2019-07-02 20:25:39 UTC
7
+++ Modules/_posixsubprocess.c
8
@@ -236,8 +236,15 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_
9
         start_fd = keep_fd + 1;
10
     }
11
     if (start_fd <= end_fd) {
12
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
13
-            close(fd_num);
14
+#ifdef __FreeBSD__
15
+        if (end_fd >= sysconf(_SC_OPEN_MAX)) {
16
+            closefrom(start_fd);
17
+        } else
18
+#endif
19
+        {
20
+            for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
21
+                close(fd_num);
22
+            }
23
         }
24
     }
25
 }
(-)lang/python36/files/patch-Modules_posixmodule.c (-26 lines)
Lines 1-26 Link Here
1
# Add closefrom(2) support
2
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274
3
# https://bugs.python.org/issue38061
4
# TODO: Upstream
5
6
--- Modules/posixmodule.c.orig	2019-07-02 20:25:39 UTC
7
+++ Modules/posixmodule.c
8
@@ -7685,8 +7685,16 @@ os_closerange_impl(PyObject *module, int fd_low, int f
9
     int i;
10
     Py_BEGIN_ALLOW_THREADS
11
     _Py_BEGIN_SUPPRESS_IPH
12
-    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
13
-        close(i);
14
+    fd_low = Py_MAX(fd_low, 0);
15
+#ifdef __FreeBSD__
16
+    if (fd_high >= sysconf(_SC_OPEN_MAX)) {
17
+        closefrom(fd_low);
18
+    } else
19
+#endif
20
+    {
21
+        for (i = fd_low; i < fd_high; i++)
22
+            close(i);
23
+    }
24
     _Py_END_SUPPRESS_IPH
25
     Py_END_ALLOW_THREADS
26
     Py_RETURN_NONE;
(-)lang/python36/files/patch-issue40422_issue40423 (+207 lines)
Line 0 Link Here
1
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
2
index 07dd54dba9..ef1b7a8ad5 100644
3
--- Modules/_posixsubprocess.c
4
+++ Modules/_posixsubprocess.c
5
@@ -21,6 +21,8 @@
6
 #include <dirent.h>
7
 #endif
8
 
9
+#include "posixmodule.h"
10
+
11
 #ifdef _Py_MEMORY_SANITIZER
12
 # include <sanitizer/msan_interface.h>
13
 #endif
14
@@ -222,7 +222,6 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
15
     long end_fd = safe_get_max_fd();
16
     Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep);
17
     Py_ssize_t keep_seq_idx;
18
-    int fd_num;
19
     /* As py_fds_to_keep is sorted we can loop through the list closing
20
      * fds inbetween any in the keep list falling within our range. */
21
     for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
22
@@ -230,15 +229,11 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
23
         int keep_fd = PyLong_AsLong(py_keep_fd);
24
         if (keep_fd < start_fd)
25
             continue;
26
-        for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
27
-            close(fd_num);
28
-        }
29
+        _Py_closerange(start_fd, keep_fd - 1);
30
         start_fd = keep_fd + 1;
31
     }
32
     if (start_fd <= end_fd) {
33
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
34
-            close(fd_num);
35
-        }
36
+        _Py_closerange(start_fd, end_fd);
37
     }
38
 }
39
 
40
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
41
index 776a3d249a..f46df9ddf7 100644
42
--- Modules/posixmodule.c
43
+++ Modules/posixmodule.c
44
@@ -7667,6 +7667,78 @@ os_close_impl(PyObject *module, int fd)
45
     Py_RETURN_NONE;
46
 }
47
 
48
+/* Our selection logic for which function to use is as follows:
49
+ * 1. If close_range(2) is available, always prefer that; it's better for
50
+ *    contiguous ranges like this than fdwalk(3) which entails iterating over
51
+ *    the entire fd space and simply doing nothing for those outside the range.
52
+ * 2. If closefrom(2) is available, we'll attempt to use that next if we're
53
+ *    closing up to sysconf(_SC_OPEN_MAX).
54
+ * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
55
+ *    as that will be more performant if the range happens to have any chunk of
56
+ *    non-opened fd in the middle.
57
+ * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
58
+ */
59
+#ifdef __FreeBSD__
60
+#define USE_CLOSEFROM
61
+#endif /* __FreeBSD__ */
62
+
63
+#ifdef HAVE_FDWALK
64
+#define USE_FDWALK
65
+#endif /* HAVE_FDWALK */
66
+
67
+#ifdef USE_FDWALK
68
+static int
69
+_fdwalk_close_func(void *lohi, int fd)
70
+{
71
+    int lo = ((int *)lohi)[0];
72
+    int hi = ((int *)lohi)[1];
73
+
74
+    if (fd >= hi)
75
+        return 1;
76
+    else if (fd >= lo)
77
+        close(fd);
78
+    return 0;
79
+}
80
+#endif /* USE_FDWALK */
81
+
82
+/* Closes all file descriptors in [first, last], ignoring errors. */
83
+void
84
+_Py_closerange(int first, int last)
85
+{
86
+    first = Py_MAX(first, 0);
87
+    _Py_BEGIN_SUPPRESS_IPH
88
+#ifdef HAVE_CLOSE_RANGE
89
+    if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
90
+        /* Any errors encountered while closing file descriptors are ignored;
91
+         * ENOSYS means no kernel support, though,
92
+         * so we'll fallback to the other methods. */
93
+    }
94
+    else
95
+#endif /* HAVE_CLOSE_RANGE */
96
+#ifdef USE_CLOSEFROM
97
+    if (last >= sysconf(_SC_OPEN_MAX)) {
98
+        /* Any errors encountered while closing file descriptors are ignored */
99
+        closefrom(first);
100
+    }
101
+    else
102
+#endif /* USE_CLOSEFROM */
103
+#ifdef USE_FDWALK
104
+    {
105
+        int lohi[2];
106
+        lohi[0] = first;
107
+        lohi[1] = last + 1;
108
+        fdwalk(_fdwalk_close_func, lohi);
109
+    }
110
+#else
111
+    {
112
+        for (int i = first; i <= last; i++) {
113
+            /* Ignore errors */
114
+            (void)close(i);
115
+        }
116
+    }
117
+#endif /* USE_FDWALK */
118
+    _Py_END_SUPPRESS_IPH
119
+}
120
 
121
 /*[clinic input]
122
 os.closerange
123
@@ -7682,12 +7754,8 @@ static PyObject *
124
 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
125
 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
126
 {
127
-    int i;
128
     Py_BEGIN_ALLOW_THREADS
129
-    _Py_BEGIN_SUPPRESS_IPH
130
-    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
131
-        close(i);
132
-    _Py_END_SUPPRESS_IPH
133
+    _Py_closerange(fd_low, fd_high - 1);
134
     Py_END_ALLOW_THREADS
135
     Py_RETURN_NONE;
136
 }
137
diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h
138
index 1ec1833825..be2308ea86 100644
139
--- Modules/posixmodule.h
140
+++ Modules/posixmodule.h
141
@@ -19,6 +19,8 @@ PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, void *);
142
 #endif /* MS_WINDOWS */
143
 #endif
144
 
145
+PyAPI_FUNC(void) _Py_closerange(int first, int last);
146
+
147
 #ifdef __cplusplus
148
 }
149
 #endif
150
diff --git a/configure b/configure
151
index e39c16eee2..1f34b4de74 100755
152
--- configure
153
+++ configure
154
@@ -11420,9 +11420,9 @@ fi
155
 
156
 # checks for library functions
157
 for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
158
- clock confstr ctermid dup3 execv faccessat fchmod fchmodat fchown fchownat \
159
- fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
160
- futimens futimes gai_strerror getentropy \
161
+ clock close_range confstr ctermid dup3 execv faccessat fchmod fchmodat fchown \
162
+ fchownat fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate \
163
+ futimesat futimens futimes gai_strerror getentropy \
164
  getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
165
  getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
166
  initgroups kill killpg lchown linkat lstat lutimes mmap \
167
diff --git a/configure.ac b/configure.ac
168
index cf280506bd..09886eaeef 100644
169
--- configure.ac
170
+++ configure.ac
171
@@ -3531,9 +3531,9 @@ fi
172
 
173
 # checks for library functions
174
 AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
175
- clock confstr ctermid dup3 execv faccessat fchmod fchmodat fchown fchownat \
176
- fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
177
- futimens futimes gai_strerror getentropy \
178
+ clock close_range confstr ctermid dup3 execv faccessat fchmod fchmodat fchown \
179
+ fchownat fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate \
180
+ futimesat futimens futimes gai_strerror getentropy \
181
  getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
182
  getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
183
  initgroups kill killpg lchown linkat lstat lutimes mmap \
184
diff --git a/pyconfig.h.in b/pyconfig.h.in
185
index 2fbbb6d20d..a4488cbe32 100644
186
--- pyconfig.h.in
187
+++ pyconfig.h.in
188
@@ -128,6 +128,9 @@
189
 /* Define to 1 if you have the `clock_settime' function. */
190
 #undef HAVE_CLOCK_SETTIME
191
 
192
+/* Define to 1 if you have the `close_range' function. */
193
+#undef HAVE_CLOSE_RANGE
194
+
195
 /* Define if the C compiler supports computed gotos. */
196
 #undef HAVE_COMPUTED_GOTOS
197
 
198
@@ -317,6 +320,9 @@
199
 /* Define to 1 if you have the `fdopendir' function. */
200
 #undef HAVE_FDOPENDIR
201
 
202
+/* Define to 1 if you have the `fdwalk' function. */
203
+#undef HAVE_FDWALK
204
+
205
 /* Define to 1 if you have the `fexecve' function. */
206
 #undef HAVE_FEXECVE
207
 
(-)lang/python37/Makefile (+1 lines)
Lines 3-8 Link Here
3
3
4
PORTNAME=	python
4
PORTNAME=	python
5
PORTVERSION=	${PYTHON_PORTVERSION}
5
PORTVERSION=	${PYTHON_PORTVERSION}
6
PORTREVISION=	1
6
CATEGORIES=	lang python
7
CATEGORIES=	lang python
7
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
9
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
(-)lang/python37/files/patch-Modules___posixsubprocess.c (-25 lines)
Lines 1-25 Link Here
1
# Add closefrom(2) support
2
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274
3
# https://bugs.python.org/issue38061
4
# TODO: Upstream
5
6
--- Modules/_posixsubprocess.c.orig	2019-10-14 22:32:36 UTC
7
+++ Modules/_posixsubprocess.c
8
@@ -236,8 +236,15 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_
9
         start_fd = keep_fd + 1;
10
     }
11
     if (start_fd <= end_fd) {
12
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
13
-            close(fd_num);
14
+#ifdef __FreeBSD__
15
+        if (end_fd >= sysconf(_SC_OPEN_MAX)) {
16
+            closefrom(start_fd);
17
+        } else
18
+#endif
19
+        {
20
+            for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
21
+                close(fd_num);
22
+            }
23
         }
24
     }
25
 }
(-)lang/python37/files/patch-Modules_posixmodule.c (-26 lines)
Lines 1-26 Link Here
1
# Add closefrom(2) support
2
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274
3
# https://bugs.python.org/issue38061
4
# TODO: Upstream
5
6
--- Modules/posixmodule.c.orig	2019-10-14 22:32:36 UTC
7
+++ Modules/posixmodule.c
8
@@ -7810,8 +7810,16 @@ os_closerange_impl(PyObject *module, int fd_low, int f
9
     int i;
10
     Py_BEGIN_ALLOW_THREADS
11
     _Py_BEGIN_SUPPRESS_IPH
12
-    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
13
-        close(i);
14
+    fd_low = Py_MAX(fd_low, 0);
15
+#ifdef __FreeBSD__
16
+    if (fd_high >= sysconf(_SC_OPEN_MAX)) {
17
+        closefrom(fd_low);
18
+    } else
19
+#endif
20
+    {
21
+        for (i = fd_low; i < fd_high; i++)
22
+            close(i);
23
+    }
24
     _Py_END_SUPPRESS_IPH
25
     Py_END_ALLOW_THREADS
26
     Py_RETURN_NONE;
(-)lang/python37/files/patch-issue40422_issue40423 (+207 lines)
Line 0 Link Here
1
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
2
index 3cf0683ad9..fb070e4cc4 100644
3
--- Modules/_posixsubprocess.c
4
+++ Modules/_posixsubprocess.c
5
@@ -21,6 +21,8 @@
6
 #include <dirent.h>
7
 #endif
8
 
9
+#include "posixmodule.h"
10
+
11
 #ifdef _Py_MEMORY_SANITIZER
12
 # include <sanitizer/msan_interface.h>
13
 #endif
14
@@ -222,7 +222,6 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
15
     long end_fd = safe_get_max_fd();
16
     Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep);
17
     Py_ssize_t keep_seq_idx;
18
-    int fd_num;
19
     /* As py_fds_to_keep is sorted we can loop through the list closing
20
      * fds in between any in the keep list falling within our range. */
21
     for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
22
@@ -230,15 +229,11 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
23
         int keep_fd = PyLong_AsLong(py_keep_fd);
24
         if (keep_fd < start_fd)
25
             continue;
26
-        for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
27
-            close(fd_num);
28
-        }
29
+        _Py_closerange(start_fd, keep_fd - 1);
30
         start_fd = keep_fd + 1;
31
     }
32
     if (start_fd <= end_fd) {
33
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
34
-            close(fd_num);
35
-        }
36
+        _Py_closerange(start_fd, end_fd);
37
     }
38
 }
39
 
40
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
41
index 43d4302b92..7878517353 100644
42
--- Modules/posixmodule.c
43
+++ Modules/posixmodule.c
44
@@ -7820,6 +7820,78 @@ os_close_impl(PyObject *module, int fd)
45
     Py_RETURN_NONE;
46
 }
47
 
48
+/* Our selection logic for which function to use is as follows:
49
+ * 1. If close_range(2) is available, always prefer that; it's better for
50
+ *    contiguous ranges like this than fdwalk(3) which entails iterating over
51
+ *    the entire fd space and simply doing nothing for those outside the range.
52
+ * 2. If closefrom(2) is available, we'll attempt to use that next if we're
53
+ *    closing up to sysconf(_SC_OPEN_MAX).
54
+ * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
55
+ *    as that will be more performant if the range happens to have any chunk of
56
+ *    non-opened fd in the middle.
57
+ * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
58
+ */
59
+#ifdef __FreeBSD__
60
+#define USE_CLOSEFROM
61
+#endif /* __FreeBSD__ */
62
+
63
+#ifdef HAVE_FDWALK
64
+#define USE_FDWALK
65
+#endif /* HAVE_FDWALK */
66
+
67
+#ifdef USE_FDWALK
68
+static int
69
+_fdwalk_close_func(void *lohi, int fd)
70
+{
71
+    int lo = ((int *)lohi)[0];
72
+    int hi = ((int *)lohi)[1];
73
+
74
+    if (fd >= hi)
75
+        return 1;
76
+    else if (fd >= lo)
77
+        close(fd);
78
+    return 0;
79
+}
80
+#endif /* USE_FDWALK */
81
+
82
+/* Closes all file descriptors in [first, last], ignoring errors. */
83
+void
84
+_Py_closerange(int first, int last)
85
+{
86
+    first = Py_MAX(first, 0);
87
+    _Py_BEGIN_SUPPRESS_IPH
88
+#ifdef HAVE_CLOSE_RANGE
89
+    if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
90
+        /* Any errors encountered while closing file descriptors are ignored;
91
+         * ENOSYS means no kernel support, though,
92
+         * so we'll fallback to the other methods. */
93
+    }
94
+    else
95
+#endif /* HAVE_CLOSE_RANGE */
96
+#ifdef USE_CLOSEFROM
97
+    if (last >= sysconf(_SC_OPEN_MAX)) {
98
+        /* Any errors encountered while closing file descriptors are ignored */
99
+        closefrom(first);
100
+    }
101
+    else
102
+#endif /* USE_CLOSEFROM */
103
+#ifdef USE_FDWALK
104
+    {
105
+        int lohi[2];
106
+        lohi[0] = first;
107
+        lohi[1] = last + 1;
108
+        fdwalk(_fdwalk_close_func, lohi);
109
+    }
110
+#else
111
+    {
112
+        for (int i = first; i <= last; i++) {
113
+            /* Ignore errors */
114
+            (void)close(i);
115
+        }
116
+    }
117
+#endif /* USE_FDWALK */
118
+    _Py_END_SUPPRESS_IPH
119
+}
120
 
121
 /*[clinic input]
122
 os.closerange
123
@@ -7835,12 +7907,8 @@ static PyObject *
124
 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
125
 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
126
 {
127
-    int i;
128
     Py_BEGIN_ALLOW_THREADS
129
-    _Py_BEGIN_SUPPRESS_IPH
130
-    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
131
-        close(i);
132
-    _Py_END_SUPPRESS_IPH
133
+    _Py_closerange(fd_low, fd_high - 1);
134
     Py_END_ALLOW_THREADS
135
     Py_RETURN_NONE;
136
 }
137
diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h
138
index 1ec1833825..be2308ea86 100644
139
--- Modules/posixmodule.h
140
+++ Modules/posixmodule.h
141
@@ -19,6 +19,8 @@ PyAPI_FUNC(int) _Py_Gid_Converter(PyObject *, void *);
142
 #endif /* MS_WINDOWS */
143
 #endif
144
 
145
+PyAPI_FUNC(void) _Py_closerange(int first, int last);
146
+
147
 #ifdef __cplusplus
148
 }
149
 #endif
150
diff --git a/configure b/configure
151
index 829dd69bb8..2eeadec5f0 100755
152
--- configure
153
+++ configure
154
@@ -11490,9 +11490,9 @@ fi
155
 
156
 # checks for library functions
157
 for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
158
- clock confstr ctermid dup3 execv faccessat fchmod fchmodat fchown fchownat \
159
- fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
160
- futimens futimes gai_strerror getentropy \
161
+ clock close_range confstr ctermid dup3 execv faccessat fchmod fchmodat fchown \
162
+ fchownat fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate \
163
+ futimesat futimens futimes gai_strerror getentropy \
164
  getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
165
  getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
166
  if_nameindex \
167
diff --git a/configure.ac b/configure.ac
168
index f1cc8e9bcb..80952290b7 100644
169
--- configure.ac
170
+++ configure.ac
171
@@ -3574,9 +3574,9 @@ fi
172
 
173
 # checks for library functions
174
 AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
175
- clock confstr ctermid dup3 execv faccessat fchmod fchmodat fchown fchownat \
176
- fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
177
- futimens futimes gai_strerror getentropy \
178
+ clock close_range confstr ctermid dup3 execv faccessat fchmod fchmodat fchown \
179
+ fchownat fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate \
180
+ futimesat futimens futimes gai_strerror getentropy \
181
  getgrouplist getgroups getlogin getloadavg getpeername getpgid getpid \
182
  getpriority getresuid getresgid getpwent getspnam getspent getsid getwd \
183
  if_nameindex \
184
diff --git a/pyconfig.h.in b/pyconfig.h.in
185
index ebab5ff518..e1d659059c 100644
186
--- pyconfig.h.in
187
+++ pyconfig.h.in
188
@@ -128,6 +128,9 @@
189
 /* Define to 1 if you have the `clock_settime' function. */
190
 #undef HAVE_CLOCK_SETTIME
191
 
192
+/* Define to 1 if you have the `close_range' function. */
193
+#undef HAVE_CLOSE_RANGE
194
+
195
 /* Define if the C compiler supports computed gotos. */
196
 #undef HAVE_COMPUTED_GOTOS
197
 
198
@@ -324,6 +327,9 @@
199
 /* Define to 1 if you have the `fdopendir' function. */
200
 #undef HAVE_FDOPENDIR
201
 
202
+/* Define to 1 if you have the `fdwalk' function. */
203
+#undef HAVE_FDWALK
204
+
205
 /* Define to 1 if you have the `fexecve' function. */
206
 #undef HAVE_FEXECVE
207
 
(-)lang/python38/Makefile (+1 lines)
Lines 3-8 Link Here
3
3
4
PORTNAME=	python
4
PORTNAME=	python
5
PORTVERSION=	${PYTHON_PORTVERSION}
5
PORTVERSION=	${PYTHON_PORTVERSION}
6
PORTREVISION=	1
6
CATEGORIES=	lang python
7
CATEGORIES=	lang python
7
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
9
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
(-)lang/python38/files/patch-Modules___posixsubprocess.c (-25 lines)
Lines 1-25 Link Here
1
# Add closefrom(2) support
2
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274
3
# https://bugs.python.org/issue38061
4
# TODO: Upstream
5
6
--- Modules/_posixsubprocess.c.orig	2019-10-14 13:34:47 UTC
7
+++ Modules/_posixsubprocess.c
8
@@ -236,8 +236,15 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_
9
         start_fd = keep_fd + 1;
10
     }
11
     if (start_fd <= end_fd) {
12
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
13
-            close(fd_num);
14
+#if defined(__FreeBSD__)
15
+        if (end_fd >= sysconf(_SC_OPEN_MAX)) {
16
+            closefrom(start_fd);
17
+        } else
18
+#endif
19
+        {
20
+            for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
21
+                close(fd_num);
22
+            }
23
         }
24
     }
25
 }
(-)lang/python38/files/patch-Modules_posixmodule.c (-26 lines)
Lines 1-26 Link Here
1
# Add closefrom(2) support
2
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242274
3
# https://bugs.python.org/issue38061
4
# TODO: Upstream
5
6
--- Modules/posixmodule.c.orig	2019-10-14 13:34:47 UTC
7
+++ Modules/posixmodule.c
8
@@ -8460,8 +8460,16 @@ os_closerange_impl(PyObject *module, int fd_low, int f
9
     lohi[1] = fd_high;
10
     fdwalk(_fdwalk_close_func, lohi);
11
 #else
12
-    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
13
-        close(i);
14
+    fd_low = Py_MAX(fd_low, 0);
15
+#ifdef __FreeBSD__
16
+    if (fd_high >= sysconf(_SC_OPEN_MAX)) {
17
+        closefrom(fd_low);
18
+    } else
19
+#endif
20
+    {
21
+        for (i = fd_low; i < fd_high; i++)
22
+            close(i);
23
+    }
24
 #endif
25
     _Py_END_SUPPRESS_IPH
26
     Py_END_ALLOW_THREADS
(-)lang/python38/files/patch-issue40422_issue40423 (+199 lines)
Line 0 Link Here
1
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
2
index e693e53206..a26ef96e91 100644
3
--- Modules/_posixsubprocess.c
4
+++ Modules/_posixsubprocess.c
5
@@ -21,6 +21,8 @@
6
 #include <dirent.h>
7
 #endif
8
 
9
+#include "posixmodule.h"
10
+
11
 #ifdef _Py_MEMORY_SANITIZER
12
 # include <sanitizer/msan_interface.h>
13
 #endif
14
@@ -222,7 +222,6 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
15
     long end_fd = safe_get_max_fd();
16
     Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep);
17
     Py_ssize_t keep_seq_idx;
18
-    int fd_num;
19
     /* As py_fds_to_keep is sorted we can loop through the list closing
20
      * fds in between any in the keep list falling within our range. */
21
     for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
22
@@ -230,15 +229,11 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
23
         int keep_fd = PyLong_AsLong(py_keep_fd);
24
         if (keep_fd < start_fd)
25
             continue;
26
-        for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
27
-            close(fd_num);
28
-        }
29
+        _Py_closerange(start_fd, keep_fd - 1);
30
         start_fd = keep_fd + 1;
31
     }
32
     if (start_fd <= end_fd) {
33
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
34
-            close(fd_num);
35
-        }
36
+        _Py_closerange(start_fd, end_fd);
37
     }
38
 }
39
 
40
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
41
index 726e3723f9..7ef2dbc854 100644
42
--- Modules/posixmodule.c
43
+++ Modules/posixmodule.c
44
@@ -8555,8 +8555,26 @@ os_close_impl(PyObject *module, int fd)
45
     Py_RETURN_NONE;
46
 }
47
 
48
+/* Our selection logic for which function to use is as follows:
49
+ * 1. If close_range(2) is available, always prefer that; it's better for
50
+ *    contiguous ranges like this than fdwalk(3) which entails iterating over
51
+ *    the entire fd space and simply doing nothing for those outside the range.
52
+ * 2. If closefrom(2) is available, we'll attempt to use that next if we're
53
+ *    closing up to sysconf(_SC_OPEN_MAX).
54
+ * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
55
+ *    as that will be more performant if the range happens to have any chunk of
56
+ *    non-opened fd in the middle.
57
+ * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
58
+ */
59
+#ifdef __FreeBSD__
60
+#define USE_CLOSEFROM
61
+#endif /* __FreeBSD__ */
62
 
63
 #ifdef HAVE_FDWALK
64
+#define USE_FDWALK
65
+#endif /* HAVE_FDWALK */
66
+
67
+#ifdef USE_FDWALK
68
 static int
69
 _fdwalk_close_func(void *lohi, int fd)
70
 {
71
@@ -8569,7 +8587,46 @@ _fdwalk_close_func(void *lohi, int fd)
72
         close(fd);
73
     return 0;
74
 }
75
-#endif /* HAVE_FDWALK */
76
+#endif /* USE_FDWALK */
77
+
78
+/* Closes all file descriptors in [first, last], ignoring errors. */
79
+void
80
+_Py_closerange(int first, int last)
81
+{
82
+    first = Py_MAX(first, 0);
83
+    _Py_BEGIN_SUPPRESS_IPH
84
+#ifdef HAVE_CLOSE_RANGE
85
+    if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
86
+        /* Any errors encountered while closing file descriptors are ignored;
87
+         * ENOSYS means no kernel support, though,
88
+         * so we'll fallback to the other methods. */
89
+    }
90
+    else
91
+#endif /* HAVE_CLOSE_RANGE */
92
+#ifdef USE_CLOSEFROM
93
+    if (last >= sysconf(_SC_OPEN_MAX)) {
94
+        /* Any errors encountered while closing file descriptors are ignored */
95
+        closefrom(first);
96
+    }
97
+    else
98
+#endif /* USE_CLOSEFROM */
99
+#ifdef USE_FDWALK
100
+    {
101
+        int lohi[2];
102
+        lohi[0] = first;
103
+        lohi[1] = last + 1;
104
+        fdwalk(_fdwalk_close_func, lohi);
105
+    }
106
+#else
107
+    {
108
+        for (int i = first; i <= last; i++) {
109
+            /* Ignore errors */
110
+            (void)close(i);
111
+        }
112
+    }
113
+#endif /* USE_FDWALK */
114
+    _Py_END_SUPPRESS_IPH
115
+}
116
 
117
 /*[clinic input]
118
 os.closerange
119
@@ -8585,22 +8642,8 @@ static PyObject *
120
 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
121
 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
122
 {
123
-#ifdef HAVE_FDWALK
124
-    int lohi[2];
125
-#else
126
-    int i;
127
-#endif
128
     Py_BEGIN_ALLOW_THREADS
129
-    _Py_BEGIN_SUPPRESS_IPH
130
-#ifdef HAVE_FDWALK
131
-    lohi[0] = Py_MAX(fd_low, 0);
132
-    lohi[1] = fd_high;
133
-    fdwalk(_fdwalk_close_func, lohi);
134
-#else
135
-    for (i = Py_MAX(fd_low, 0); i < fd_high; i++)
136
-        close(i);
137
-#endif
138
-    _Py_END_SUPPRESS_IPH
139
+    _Py_closerange(fd_low, fd_high - 1);
140
     Py_END_ALLOW_THREADS
141
     Py_RETURN_NONE;
142
 }
143
diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h
144
index 1e00562abc..749833f71c 100644
145
--- Modules/posixmodule.h
146
+++ Modules/posixmodule.h
147
@@ -28,6 +28,8 @@ PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *);
148
 #endif /* HAVE_SIGSET_T */
149
 #endif /* Py_LIMITED_API */
150
 
151
+PyAPI_FUNC(void) _Py_closerange(int first, int last);
152
+
153
 #ifdef __cplusplus
154
 }
155
 #endif
156
diff --git a/configure b/configure
157
index 96dcd0dcd5..90b61f9f8f 100755
158
--- configure
159
+++ configure
160
@@ -11503,8 +11503,8 @@ fi
161
 
162
 # checks for library functions
163
 for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
164
- clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
165
- faccessat fchmod fchmodat fchown fchownat \
166
+ clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
167
+ explicit_memset faccessat fchmod fchmodat fchown fchownat \
168
  fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
169
  futimens futimes gai_strerror getentropy \
170
  getgrgid_r getgrnam_r \
171
diff --git a/configure.ac b/configure.ac
172
index 18a044629a..fbb051d49c 100644
173
--- configure.ac
174
+++ configure.ac
175
@@ -3560,8 +3560,8 @@ fi
176
 
177
 # checks for library functions
178
 AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
179
- clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
180
- faccessat fchmod fchmodat fchown fchownat \
181
+ clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
182
+ explicit_memset faccessat fchmod fchmodat fchown fchownat \
183
  fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
184
  futimens futimes gai_strerror getentropy \
185
  getgrgid_r getgrnam_r \
186
diff --git a/pyconfig.h.in b/pyconfig.h.in
187
index 4263a712c3..166d278f7c 100644
188
--- pyconfig.h.in
189
+++ pyconfig.h.in
190
@@ -136,6 +136,9 @@
191
 /* Define to 1 if you have the `clock_settime' function. */
192
 #undef HAVE_CLOCK_SETTIME
193
 
194
+/* Define to 1 if you have the `close_range' function. */
195
+#undef HAVE_CLOSE_RANGE
196
+
197
 /* Define if the C compiler supports computed gotos. */
198
 #undef HAVE_COMPUTED_GOTOS
199
 
(-)lang/python39/Makefile (+1 lines)
Lines 3-8 Link Here
3
3
4
PORTNAME=	python
4
PORTNAME=	python
5
PORTVERSION=	${PYTHON_PORTVERSION}
5
PORTVERSION=	${PYTHON_PORTVERSION}
6
PORTREVISION=	1
6
CATEGORIES=	lang python
7
CATEGORIES=	lang python
7
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
MASTER_SITES=	PYTHON/ftp/python/${PORTVERSION}
8
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
9
PKGNAMESUFFIX=	${PYTHON_SUFFIX}
(-)lang/python39/files/patch-issue40422_issue40423 (+206 lines)
Line 0 Link Here
1
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
2
index 5d1691ace4..ed046fc5c1 100644
3
--- Modules/_posixsubprocess.c
4
+++ Modules/_posixsubprocess.c
5
@@ -250,7 +250,6 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
6
     long end_fd = safe_get_max_fd();
7
     Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep);
8
     Py_ssize_t keep_seq_idx;
9
-    int fd_num;
10
     /* As py_fds_to_keep is sorted we can loop through the list closing
11
      * fds in between any in the keep list falling within our range. */
12
     for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
13
@@ -258,21 +257,11 @@ _close_fds_by_brute_force(long start_fd, PyObject *py_fds_to_keep)
14
         int keep_fd = PyLong_AsLong(py_keep_fd);
15
         if (keep_fd < start_fd)
16
             continue;
17
-        for (fd_num = start_fd; fd_num < keep_fd; ++fd_num) {
18
-            close(fd_num);
19
-        }
20
+        _Py_closerange(start_fd, keep_fd - 1);
21
         start_fd = keep_fd + 1;
22
     }
23
     if (start_fd <= end_fd) {
24
-#if defined(__FreeBSD__)
25
-        /* Any errors encountered while closing file descriptors are ignored */
26
-        closefrom(start_fd);
27
-#else
28
-        for (fd_num = start_fd; fd_num < end_fd; ++fd_num) {
29
-            /* Ignore errors */
30
-            (void)close(fd_num);
31
-        }
32
-#endif
33
+        _Py_closerange(start_fd, end_fd);
34
     }
35
 }
36
 
37
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
38
index 01e8bcbd29..f6aad2e02e 100644
39
--- Modules/posixmodule.c
40
+++ Modules/posixmodule.c
41
@@ -8691,8 +8691,26 @@ os_close_impl(PyObject *module, int fd)
42
     Py_RETURN_NONE;
43
 }
44
 
45
+/* Our selection logic for which function to use is as follows:
46
+ * 1. If close_range(2) is available, always prefer that; it's better for
47
+ *    contiguous ranges like this than fdwalk(3) which entails iterating over
48
+ *    the entire fd space and simply doing nothing for those outside the range.
49
+ * 2. If closefrom(2) is available, we'll attempt to use that next if we're
50
+ *    closing up to sysconf(_SC_OPEN_MAX).
51
+ * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
52
+ *    as that will be more performant if the range happens to have any chunk of
53
+ *    non-opened fd in the middle.
54
+ * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
55
+ */
56
+#ifdef __FreeBSD__
57
+#define USE_CLOSEFROM
58
+#endif /* __FreeBSD__ */
59
 
60
 #ifdef HAVE_FDWALK
61
+#define USE_FDWALK
62
+#endif /* HAVE_FDWALK */
63
+
64
+#ifdef USE_FDWALK
65
 static int
66
 _fdwalk_close_func(void *lohi, int fd)
67
 {
68
@@ -8708,7 +8726,46 @@ _fdwalk_close_func(void *lohi, int fd)
69
     }
70
     return 0;
71
 }
72
-#endif /* HAVE_FDWALK */
73
+#endif /* USE_FDWALK */
74
+
75
+/* Closes all file descriptors in [first, last], ignoring errors. */
76
+void
77
+_Py_closerange(int first, int last)
78
+{
79
+    first = Py_MAX(first, 0);
80
+    _Py_BEGIN_SUPPRESS_IPH
81
+#ifdef HAVE_CLOSE_RANGE
82
+    if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
83
+        /* Any errors encountered while closing file descriptors are ignored;
84
+         * ENOSYS means no kernel support, though,
85
+         * so we'll fallback to the other methods. */
86
+    }
87
+    else
88
+#endif /* HAVE_CLOSE_RANGE */
89
+#ifdef USE_CLOSEFROM
90
+    if (last >= sysconf(_SC_OPEN_MAX)) {
91
+        /* Any errors encountered while closing file descriptors are ignored */
92
+        closefrom(first);
93
+    }
94
+    else
95
+#endif /* USE_CLOSEFROM */
96
+#ifdef USE_FDWALK
97
+    {
98
+        int lohi[2];
99
+        lohi[0] = first;
100
+        lohi[1] = last + 1;
101
+        fdwalk(_fdwalk_close_func, lohi);
102
+    }
103
+#else
104
+    {
105
+        for (int i = first; i <= last; i++) {
106
+            /* Ignore errors */
107
+            (void)close(i);
108
+        }
109
+    }
110
+#endif /* USE_FDWALK */
111
+    _Py_END_SUPPRESS_IPH
112
+}
113
 
114
 /*[clinic input]
115
 os.closerange
116
@@ -8724,32 +8781,8 @@ static PyObject *
117
 os_closerange_impl(PyObject *module, int fd_low, int fd_high)
118
 /*[clinic end generated code: output=0ce5c20fcda681c2 input=5855a3d053ebd4ec]*/
119
 {
120
-#ifdef HAVE_FDWALK
121
-    int lohi[2];
122
-#endif
123
     Py_BEGIN_ALLOW_THREADS
124
-    _Py_BEGIN_SUPPRESS_IPH
125
-#ifdef HAVE_FDWALK
126
-    lohi[0] = Py_MAX(fd_low, 0);
127
-    lohi[1] = fd_high;
128
-    fdwalk(_fdwalk_close_func, lohi);
129
-#else
130
-    fd_low = Py_MAX(fd_low, 0);
131
-#ifdef __FreeBSD__
132
-    if (fd_high >= sysconf(_SC_OPEN_MAX)) {
133
-        /* Any errors encountered while closing file descriptors are ignored */
134
-        closefrom(fd_low);
135
-    }
136
-    else
137
-#endif
138
-    {
139
-        for (int i = fd_low; i < fd_high; i++) {
140
-            /* Ignore errors */
141
-            (void)close(i);
142
-        }
143
-    }
144
-#endif
145
-    _Py_END_SUPPRESS_IPH
146
+    _Py_closerange(fd_low, fd_high - 1);
147
     Py_END_ALLOW_THREADS
148
     Py_RETURN_NONE;
149
 }
150
diff --git a/Modules/posixmodule.h b/Modules/posixmodule.h
151
index 1e00562abc..749833f71c 100644
152
--- Modules/posixmodule.h
153
+++ Modules/posixmodule.h
154
@@ -28,6 +28,8 @@ PyAPI_FUNC(int) _Py_Sigset_Converter(PyObject *, void *);
155
 #endif /* HAVE_SIGSET_T */
156
 #endif /* Py_LIMITED_API */
157
 
158
+PyAPI_FUNC(void) _Py_closerange(int first, int last);
159
+
160
 #ifdef __cplusplus
161
 }
162
 #endif
163
diff --git a/configure b/configure
164
index 9e6fd46583..de517223f6 100755
165
--- configure
166
+++ configure
167
@@ -11668,8 +11668,8 @@ fi
168
 
169
 # checks for library functions
170
 for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
171
- clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
172
- faccessat fchmod fchmodat fchown fchownat \
173
+ clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
174
+ explicit_memset faccessat fchmod fchmodat fchown fchownat \
175
  fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
176
  futimens futimes gai_strerror getentropy \
177
  getgrgid_r getgrnam_r \
178
diff --git a/configure.ac b/configure.ac
179
index d60f05251a..faa187af69 100644
180
--- configure.ac
181
+++ configure.ac
182
@@ -3664,8 +3664,8 @@ fi
183
 
184
 # checks for library functions
185
 AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
186
- clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
187
- faccessat fchmod fchmodat fchown fchownat \
188
+ clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
189
+ explicit_memset faccessat fchmod fchmodat fchown fchownat \
190
  fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
191
  futimens futimes gai_strerror getentropy \
192
  getgrgid_r getgrnam_r \
193
diff --git a/pyconfig.h.in b/pyconfig.h.in
194
index c9589cd102..449b25f551 100644
195
--- pyconfig.h.in
196
+++ pyconfig.h.in
197
@@ -136,6 +136,9 @@
198
 /* Define to 1 if you have the `clock_settime' function. */
199
 #undef HAVE_CLOCK_SETTIME
200
 
201
+/* Define to 1 if you have the `close_range' function. */
202
+#undef HAVE_CLOSE_RANGE
203
+
204
 /* Define if the C compiler supports computed gotos. */
205
 #undef HAVE_COMPUTED_GOTOS
206
 

Return to bug 250322