summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyle Evans <kevans91@users.noreply.github.com>2020-10-11 15:18:53 -0500
committerGitHub <noreply@github.com>2020-10-11 13:18:53 -0700
commit1800c600801709958af66bebfa683a4e7570810f (patch)
tree6ac63c960220b9e666db1e8d2f36dd3f39068c92
parentc230fde8475e4e5581e74a4235654d17ccf4cff8 (diff)
downloadcpython-git-1800c600801709958af66bebfa683a4e7570810f.tar.gz
bpo-40423: Optimization: use close_range(2) if available (GH-22651)
close_range(2) should be preferred at all times if it's available, otherwise we'll use closefrom(2) if available with a fallback to fdwalk(3) or plain old loop over fd range in order of most efficient to least. [note that this version does check for ENOSYS, but currently ignores all other errors] Automerge-Triggered-By: @pablogsal
-rw-r--r--Misc/NEWS.d/next/C API/2020-10-11-19-17-44.bpo-40423.GsmgEj.rst3
-rw-r--r--Modules/posixmodule.c17
-rwxr-xr-xconfigure4
-rw-r--r--configure.ac4
-rw-r--r--pyconfig.h.in3
5 files changed, 24 insertions, 7 deletions
diff --git a/Misc/NEWS.d/next/C API/2020-10-11-19-17-44.bpo-40423.GsmgEj.rst b/Misc/NEWS.d/next/C API/2020-10-11-19-17-44.bpo-40423.GsmgEj.rst
new file mode 100644
index 0000000000..44e571ebf8
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2020-10-11-19-17-44.bpo-40423.GsmgEj.rst
@@ -0,0 +1,3 @@
+The :mod:`subprocess` module and ``os.closerange`` will now use the
+``close_range(low, high, flags)`` syscall when it is available for more
+efficient closing of ranges of descriptors. \ No newline at end of file
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 321eaec63c..2e0caaa3e5 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -8741,12 +8741,15 @@ os_close_impl(PyObject *module, int fd)
}
/* Our selection logic for which function to use is as follows:
- * 1. If closefrom(2) is available, we'll attempt to use that next if we're
+ * 1. If close_range(2) is available, always prefer that; it's better for
+ * contiguous ranges like this than fdwalk(3) which entails iterating over
+ * the entire fd space and simply doing nothing for those outside the range.
+ * 2. If closefrom(2) is available, we'll attempt to use that next if we're
* closing up to sysconf(_SC_OPEN_MAX).
- * 1a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
+ * 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
* as that will be more performant if the range happens to have any chunk of
* non-opened fd in the middle.
- * 1b. If fdwalk(3) isn't available, just do a plain close(2) loop.
+ * 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
*/
#ifdef __FreeBSD__
#define USE_CLOSEFROM
@@ -8779,6 +8782,14 @@ void
_Py_closerange(int first, int last)
{
first = Py_MAX(first, 0);
+#ifdef HAVE_CLOSE_RANGE
+ if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
+ /* Any errors encountered while closing file descriptors are ignored;
+ * ENOSYS means no kernel support, though,
+ * so we'll fallback to the other methods. */
+ }
+ else
+#endif /* HAVE_CLOSE_RANGE */
#ifdef USE_CLOSEFROM
if (last >= sysconf(_SC_OPEN_MAX)) {
/* Any errors encountered while closing file descriptors are ignored */
diff --git a/configure b/configure
index ad74754e9a..89577d85a4 100755
--- a/configure
+++ b/configure
@@ -11672,8 +11672,8 @@ fi
# checks for library functions
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
- faccessat fchmod fchmodat fchown fchownat \
+ clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
getgrgid_r getgrnam_r \
diff --git a/configure.ac b/configure.ac
index f0bc8c6258..3ec274c576 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3664,8 +3664,8 @@ fi
# checks for library functions
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
- clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
- faccessat fchmod fchmodat fchown fchownat \
+ clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
+ explicit_memset faccessat fchmod fchmodat fchown fchownat \
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
futimens futimes gai_strerror getentropy \
getgrgid_r getgrnam_r \
diff --git a/pyconfig.h.in b/pyconfig.h.in
index c162a3c33e..298cb4fa12 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -139,6 +139,9 @@
/* Define to 1 if you have the `clock_settime' function. */
#undef HAVE_CLOCK_SETTIME
+/* Define to 1 if you have the `close_range' function. */
+#undef HAVE_CLOSE_RANGE
+
/* Define if the C compiler supports computed gotos. */
#undef HAVE_COMPUTED_GOTOS