Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-113117: Support posix_spawn in subprocess.Popen with close_fds=True #113118

Merged
merged 10 commits into from
Dec 17, 2023
15 changes: 13 additions & 2 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4583,10 +4583,17 @@ written in Python, such as a mail server's external command delivery program.

Performs ``os.dup2(fd, new_fd)``.

.. data:: POSIX_SPAWN_CLOSEFROM

(``os.POSIX_SPAWN_CLOSEFROM``, *fd*)

Performs ``os.closerange(fd, INF)``.

These tuples correspond to the C library
:c:func:`!posix_spawn_file_actions_addopen`,
:c:func:`!posix_spawn_file_actions_addclose`, and
:c:func:`!posix_spawn_file_actions_adddup2` API calls used to prepare
:c:func:`!posix_spawn_file_actions_addclose`,
:c:func:`!posix_spawn_file_actions_adddup2`, and
:c:func:`!posix_spawn_file_actions_addclosefrom_np` API calls used to prepare
for the :c:func:`!posix_spawn` call itself.

The *setpgroup* argument will set the process group of the child to the value
Expand Down Expand Up @@ -4628,6 +4635,10 @@ written in Python, such as a mail server's external command delivery program.

.. versionadded:: 3.8

.. versionchanged:: 3.13
``os.POSIX_SPAWN_CLOSEFROM`` is available on platforms where
:c:func:`!posix_spawn_file_actions_addclosefrom_np` exists.

.. availability:: Unix, not Emscripten, not WASI.

.. function:: posix_spawnp(path, argv, env, *, file_actions=None, \
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,11 @@ Optimizations
* :func:`textwrap.indent` is now ~30% faster than before for large input.
(Contributed by Inada Naoki in :gh:`107369`.)

* The :mod:`subprocess` module can now use the :func:`os.posix_spawn` function
with ``close_fds=True`` on platforms where
``posix_spawn_file_actions_addclosefrom_np`` is available.
(Contributed by Jakub Kulik in :gh:`113117`.)


Deprecated
==========
Expand Down
11 changes: 8 additions & 3 deletions Lib/subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,6 +748,7 @@ def _use_posix_spawn():
# guarantee the given libc/syscall API will be used.
_USE_POSIX_SPAWN = _use_posix_spawn()
_USE_VFORK = True
_HAVE_POSIX_SPAWN_CLOSEFROM = hasattr(os, 'POSIX_SPAWN_CLOSEFROM')


class Popen:
Expand Down Expand Up @@ -1751,7 +1752,7 @@ def _get_handles(self, stdin, stdout, stderr):
errread, errwrite)


def _posix_spawn(self, args, executable, env, restore_signals,
def _posix_spawn(self, args, executable, env, restore_signals, close_fds,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite):
Expand Down Expand Up @@ -1780,6 +1781,10 @@ def _posix_spawn(self, args, executable, env, restore_signals,
):
if fd != -1:
file_actions.append((os.POSIX_SPAWN_DUP2, fd, fd2))

if close_fds:
file_actions.append((os.POSIX_SPAWN_CLOSEFROM, 3))

if file_actions:
kwargs['file_actions'] = file_actions

Expand Down Expand Up @@ -1827,7 +1832,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
if (_USE_POSIX_SPAWN
and os.path.dirname(executable)
and preexec_fn is None
and not close_fds
and (not close_fds or _HAVE_POSIX_SPAWN_CLOSEFROM)
and not pass_fds
and cwd is None
and (p2cread == -1 or p2cread > 2)
Expand All @@ -1839,7 +1844,7 @@ def _execute_child(self, args, executable, preexec_fn, close_fds,
and gids is None
and uid is None
and umask < 0):
self._posix_spawn(args, executable, env, restore_signals,
self._posix_spawn(args, executable, env, restore_signals, close_fds,
p2cread, p2cwrite,
c2pread, c2pwrite,
errread, errwrite)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
The :mod:`subprocess` module can now use the :func:`os.posix_spawn` function
with ``close_fds=True`` on platforms where
``posix_spawn_file_actions_addclosefrom_np`` is available.
Patch by Jakub Kulik.
24 changes: 24 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6787,6 +6787,9 @@ enum posix_spawn_file_actions_identifier {
POSIX_SPAWN_OPEN,
POSIX_SPAWN_CLOSE,
POSIX_SPAWN_DUP2
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
,POSIX_SPAWN_CLOSEFROM
#endif
};

#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
Expand Down Expand Up @@ -7027,6 +7030,24 @@ parse_file_actions(PyObject *file_actions,
}
break;
}
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
case POSIX_SPAWN_CLOSEFROM: {
int fd;
if (!PyArg_ParseTuple(file_action, "Oi"
";A closefrom file_action tuple must have 2 elements",
&tag_obj, &fd))
{
goto fail;
}
errno = posix_spawn_file_actions_addclosefrom_np(file_actionsp,
gpshead marked this conversation as resolved.
Show resolved Hide resolved
fd);
if (errno) {
posix_error();
goto fail;
}
break;
}
#endif
default: {
PyErr_SetString(PyExc_TypeError,
"Unknown file_actions identifier");
Expand Down Expand Up @@ -16723,6 +16744,9 @@ all_ins(PyObject *m)
if (PyModule_AddIntConstant(m, "POSIX_SPAWN_OPEN", POSIX_SPAWN_OPEN)) return -1;
if (PyModule_AddIntConstant(m, "POSIX_SPAWN_CLOSE", POSIX_SPAWN_CLOSE)) return -1;
if (PyModule_AddIntConstant(m, "POSIX_SPAWN_DUP2", POSIX_SPAWN_DUP2)) return -1;
#ifdef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP
if (PyModule_AddIntMacro(m, POSIX_SPAWN_CLOSEFROM)) return -1;
#endif
#endif

#if defined(HAVE_SPAWNV) || defined (HAVE_RTPSPAWN)
Expand Down
6 changes: 6 additions & 0 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -4757,6 +4757,7 @@ AC_CHECK_FUNCS([ \
lockf lstat lutimes madvise mbrtowc memrchr mkdirat mkfifo mkfifoat \
mknod mknodat mktime mmap mremap nice openat opendir pathconf pause pipe \
pipe2 plock poll posix_fadvise posix_fallocate posix_spawn posix_spawnp \
posix_spawn_file_actions_addclosefrom_np \
pread preadv preadv2 pthread_condattr_setclock pthread_init pthread_kill \
pwrite pwritev pwritev2 readlink readlinkat readv realpath renameat \
rtpSpawn sched_get_priority_max sched_rr_get_interval sched_setaffinity \
Expand Down
4 changes: 4 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -905,6 +905,10 @@
/* Define to 1 if you have the `posix_spawnp' function. */
#undef HAVE_POSIX_SPAWNP

/* Define to 1 if you have the `posix_spawn_file_actions_addclosefrom_np'
function. */
#undef HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSEFROM_NP

/* Define to 1 if you have the `pread' function. */
#undef HAVE_PREAD

Expand Down
Loading