Skip to content

Commit 1800c60

Browse files
authored
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
1 parent c230fde commit 1800c60

File tree

5 files changed

+24
-7
lines changed

5 files changed

+24
-7
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The :mod:`subprocess` module and ``os.closerange`` will now use the
2+
``close_range(low, high, flags)`` syscall when it is available for more
3+
efficient closing of ranges of descriptors.

‎Modules/posixmodule.c‎

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8741,12 +8741,15 @@ os_close_impl(PyObject *module, int fd)
87418741
}
87428742

87438743
/* Our selection logic for which function to use is as follows:
8744-
* 1. If closefrom(2) is available, we'll attempt to use that next if we're
8744+
* 1. If close_range(2) is available, always prefer that; it's better for
8745+
* contiguous ranges like this than fdwalk(3) which entails iterating over
8746+
* the entire fd space and simply doing nothing for those outside the range.
8747+
* 2. If closefrom(2) is available, we'll attempt to use that next if we're
87458748
* closing up to sysconf(_SC_OPEN_MAX).
8746-
* 1a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
8749+
* 2a. Fallback to fdwalk(3) if we're not closing up to sysconf(_SC_OPEN_MAX),
87478750
* as that will be more performant if the range happens to have any chunk of
87488751
* non-opened fd in the middle.
8749-
* 1b. If fdwalk(3) isn't available, just do a plain close(2) loop.
8752+
* 2b. If fdwalk(3) isn't available, just do a plain close(2) loop.
87508753
*/
87518754
#ifdef __FreeBSD__
87528755
#define USE_CLOSEFROM
@@ -8779,6 +8782,14 @@ void
87798782
_Py_closerange(int first, int last)
87808783
{
87818784
first = Py_MAX(first, 0);
8785+
#ifdef HAVE_CLOSE_RANGE
8786+
if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
8787+
/* Any errors encountered while closing file descriptors are ignored;
8788+
* ENOSYS means no kernel support, though,
8789+
* so we'll fallback to the other methods. */
8790+
}
8791+
else
8792+
#endif /* HAVE_CLOSE_RANGE */
87828793
#ifdef USE_CLOSEFROM
87838794
if (last >= sysconf(_SC_OPEN_MAX)) {
87848795
/* Any errors encountered while closing file descriptors are ignored */

‎configure‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11672,8 +11672,8 @@ fi
1167211672

1167311673
# checks for library functions
1167411674
for ac_func in alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
11675-
clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
11676-
faccessat fchmod fchmodat fchown fchownat \
11675+
clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
11676+
explicit_memset faccessat fchmod fchmodat fchown fchownat \
1167711677
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
1167811678
futimens futimes gai_strerror getentropy \
1167911679
getgrgid_r getgrnam_r \

‎configure.ac‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3664,8 +3664,8 @@ fi
36643664

36653665
# checks for library functions
36663666
AC_CHECK_FUNCS(alarm accept4 setitimer getitimer bind_textdomain_codeset chown \
3667-
clock confstr copy_file_range ctermid dup3 execv explicit_bzero explicit_memset \
3668-
faccessat fchmod fchmodat fchown fchownat \
3667+
clock confstr close_range copy_file_range ctermid dup3 execv explicit_bzero \
3668+
explicit_memset faccessat fchmod fchmodat fchown fchownat \
36693669
fdwalk fexecve fdopendir fork fpathconf fstatat ftime ftruncate futimesat \
36703670
futimens futimes gai_strerror getentropy \
36713671
getgrgid_r getgrnam_r \

‎pyconfig.h.in‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,9 @@
139139
/* Define to 1 if you have the `clock_settime' function. */
140140
#undef HAVE_CLOCK_SETTIME
141141

142+
/* Define to 1 if you have the `close_range' function. */
143+
#undef HAVE_CLOSE_RANGE
144+
142145
/* Define if the C compiler supports computed gotos. */
143146
#undef HAVE_COMPUTED_GOTOS
144147

0 commit comments

Comments
 (0)