gh-113119 fix environment handling in subprocess.Popen when posix_spawn is used (#113120)

* Allow posix_spawn to inherit environment form parent environ variable.

With this change, posix_spawn call can behave similarly to execv with regards to environments when used in subprocess functions.
This commit is contained in:
Jakub Kulík 2023-12-17 06:19:05 +01:00 committed by GitHub
parent cde1335485
commit 48c907a15c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 10 deletions

View File

@ -4570,7 +4570,8 @@ written in Python, such as a mail server's external command delivery program.
Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`. Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`.
The positional-only arguments *path*, *args*, and *env* are similar to The positional-only arguments *path*, *args*, and *env* are similar to
:func:`execve`. :func:`execve`. *env* is allowed to be ``None``, in which case current
process' environment is used.
The *path* parameter is the path to the executable file. The *path* should The *path* parameter is the path to the executable file. The *path* should
contain a directory. Use :func:`posix_spawnp` to pass an executable file contain a directory. Use :func:`posix_spawnp` to pass an executable file
@ -4645,6 +4646,9 @@ written in Python, such as a mail server's external command delivery program.
.. versionadded:: 3.8 .. versionadded:: 3.8
.. versionchanged:: 3.13
*env* parameter accepts ``None``.
.. availability:: Unix, not Emscripten, not WASI. .. availability:: Unix, not Emscripten, not WASI.
.. function:: posix_spawnp(path, argv, env, *, file_actions=None, \ .. function:: posix_spawnp(path, argv, env, *, file_actions=None, \

View File

@ -289,6 +289,10 @@ os
``False`` on Windows. ``False`` on Windows.
(Contributed by Serhiy Storchaka in :gh:`59616`) (Contributed by Serhiy Storchaka in :gh:`59616`)
* :func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned
process use the current process environment.
(Contributed by Jakub Kulik in :gh:`113119`.)
pathlib pathlib
------- -------

View File

@ -1756,9 +1756,6 @@ def _posix_spawn(self, args, executable, env, restore_signals,
c2pread, c2pwrite, c2pread, c2pwrite,
errread, errwrite): errread, errwrite):
"""Execute program using os.posix_spawn().""" """Execute program using os.posix_spawn()."""
if env is None:
env = os.environ
kwargs = {} kwargs = {}
if restore_signals: if restore_signals:
# See _Py_RestoreSignals() in Python/pylifecycle.c # See _Py_RestoreSignals() in Python/pylifecycle.c

View File

@ -0,0 +1,2 @@
:func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned
process use the current process environment. Patch by Jakub Kulik.

View File

@ -7129,9 +7129,9 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
return NULL; return NULL;
} }
if (!PyMapping_Check(env)) { if (!PyMapping_Check(env) && env != Py_None) {
PyErr_Format(PyExc_TypeError, PyErr_Format(PyExc_TypeError,
"%s: environment must be a mapping object", func_name); "%s: environment must be a mapping object or None", func_name);
goto exit; goto exit;
} }
@ -7145,10 +7145,14 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
goto exit; goto exit;
} }
if (env == Py_None) {
envlist = environ;
} else {
envlist = parse_envlist(env, &envc); envlist = parse_envlist(env, &envc);
if (envlist == NULL) { if (envlist == NULL) {
goto exit; goto exit;
} }
}
if (file_actions != NULL && file_actions != Py_None) { if (file_actions != NULL && file_actions != Py_None) {
/* There is a bug in old versions of glibc that makes some of the /* There is a bug in old versions of glibc that makes some of the
@ -7210,7 +7214,7 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
if (attrp) { if (attrp) {
(void)posix_spawnattr_destroy(attrp); (void)posix_spawnattr_destroy(attrp);
} }
if (envlist) { if (envlist && envlist != environ) {
free_string_array(envlist, envc); free_string_array(envlist, envc);
} }
if (argvlist) { if (argvlist) {