Skip to content

Commit bd6de62

Browse files
kulikjakaisk
authored andcommitted
pythongh-113119 fix environment handling in subprocess.Popen when posix_spawn is used (python#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.
1 parent 409c350 commit bd6de62

File tree

5 files changed

+21
-10
lines changed

5 files changed

+21
-10
lines changed

Doc/library/os.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -4570,7 +4570,8 @@ written in Python, such as a mail server's external command delivery program.
45704570
Most users should use :func:`subprocess.run` instead of :func:`posix_spawn`.
45714571

45724572
The positional-only arguments *path*, *args*, and *env* are similar to
4573-
:func:`execve`.
4573+
:func:`execve`. *env* is allowed to be ``None``, in which case current
4574+
process' environment is used.
45744575

45754576
The *path* parameter is the path to the executable file. The *path* should
45764577
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.
46454646

46464647
.. versionadded:: 3.8
46474648

4649+
.. versionchanged:: 3.13
4650+
*env* parameter accepts ``None``.
4651+
46484652
.. availability:: Unix, not Emscripten, not WASI.
46494653

46504654
.. function:: posix_spawnp(path, argv, env, *, file_actions=None, \

Doc/whatsnew/3.13.rst

+4
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,10 @@ os
289289
``False`` on Windows.
290290
(Contributed by Serhiy Storchaka in :gh:`59616`)
291291

292+
* :func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned
293+
process use the current process environment.
294+
(Contributed by Jakub Kulik in :gh:`113119`.)
295+
292296
pathlib
293297
-------
294298

Lib/subprocess.py

-3
Original file line numberDiff line numberDiff line change
@@ -1756,9 +1756,6 @@ def _posix_spawn(self, args, executable, env, restore_signals,
17561756
c2pread, c2pwrite,
17571757
errread, errwrite):
17581758
"""Execute program using os.posix_spawn()."""
1759-
if env is None:
1760-
env = os.environ
1761-
17621759
kwargs = {}
17631760
if restore_signals:
17641761
# See _Py_RestoreSignals() in Python/pylifecycle.c
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
:func:`os.posix_spawn` now accepts ``env=None``, which makes the newly spawned
2+
process use the current process environment. Patch by Jakub Kulik.

Modules/posixmodule.c

+10-6
Original file line numberDiff line numberDiff line change
@@ -7129,9 +7129,9 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
71297129
return NULL;
71307130
}
71317131

7132-
if (!PyMapping_Check(env)) {
7132+
if (!PyMapping_Check(env) && env != Py_None) {
71337133
PyErr_Format(PyExc_TypeError,
7134-
"%s: environment must be a mapping object", func_name);
7134+
"%s: environment must be a mapping object or None", func_name);
71357135
goto exit;
71367136
}
71377137

@@ -7145,9 +7145,13 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
71457145
goto exit;
71467146
}
71477147

7148-
envlist = parse_envlist(env, &envc);
7149-
if (envlist == NULL) {
7150-
goto exit;
7148+
if (env == Py_None) {
7149+
envlist = environ;
7150+
} else {
7151+
envlist = parse_envlist(env, &envc);
7152+
if (envlist == NULL) {
7153+
goto exit;
7154+
}
71517155
}
71527156

71537157
if (file_actions != NULL && file_actions != Py_None) {
@@ -7210,7 +7214,7 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
72107214
if (attrp) {
72117215
(void)posix_spawnattr_destroy(attrp);
72127216
}
7213-
if (envlist) {
7217+
if (envlist && envlist != environ) {
72147218
free_string_array(envlist, envc);
72157219
}
72167220
if (argvlist) {

0 commit comments

Comments
 (0)