]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-113119 fix environment handling in subprocess.Popen when posix_spawn is used ...
authorJakub Kulík <Kulikjak@gmail.com>
Sun, 17 Dec 2023 05:19:05 +0000 (06:19 +0100)
committerGitHub <noreply@github.com>
Sun, 17 Dec 2023 05:19:05 +0000 (05:19 +0000)
* 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.

Doc/library/os.rst
Doc/whatsnew/3.13.rst
Lib/subprocess.py
Misc/NEWS.d/next/Library/2023-12-15-18-13-59.gh-issue-113119.al-569.rst [new file with mode: 0644]
Modules/posixmodule.c

index 2ff0b73560ac4ca3844bbbe0e277afdb0b9c4596..a079f1fa604bf494b258d5982e577a3368e4fd9c 100644 (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`.
 
    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
    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
 
+   .. versionchanged:: 3.13
+      *env* parameter accepts ``None``.
+
    .. availability:: Unix, not Emscripten, not WASI.
 
 .. function:: posix_spawnp(path, argv, env, *, file_actions=None, \
index ce4f66b97a0be424dd11debfcb97b393129858f0..4af023566ff0bc6f38882964aa3646af79c4c0b6 100644 (file)
@@ -289,6 +289,10 @@ os
   ``False`` on Windows.
   (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
 -------
 
index d6edd1a9807d1bee9c44dafd0c2c12d22a2b537c..1919ea4bddeedac174df3b4ea9993cc8faeb8af0 100644 (file)
@@ -1756,9 +1756,6 @@ class Popen:
                          c2pread, c2pwrite,
                          errread, errwrite):
             """Execute program using os.posix_spawn()."""
-            if env is None:
-                env = os.environ
-
             kwargs = {}
             if restore_signals:
                 # See _Py_RestoreSignals() in Python/pylifecycle.c
diff --git a/Misc/NEWS.d/next/Library/2023-12-15-18-13-59.gh-issue-113119.al-569.rst b/Misc/NEWS.d/next/Library/2023-12-15-18-13-59.gh-issue-113119.al-569.rst
new file mode 100644 (file)
index 0000000..94087b0
--- /dev/null
@@ -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.
index b464a28e63b8acb3b47645adf1f475a166ac5d50..2dc5d7d81db9734f775e2fc39cce5bf59372eb2a 100644 (file)
@@ -7129,9 +7129,9 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
         return NULL;
     }
 
-    if (!PyMapping_Check(env)) {
+    if (!PyMapping_Check(env) && env != Py_None) {
         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;
     }
 
@@ -7145,9 +7145,13 @@ py_posix_spawn(int use_posix_spawnp, PyObject *module, path_t *path, PyObject *a
         goto exit;
     }
 
-    envlist = parse_envlist(env, &envc);
-    if (envlist == NULL) {
-        goto exit;
+    if (env == Py_None) {
+        envlist = environ;
+    } else {
+        envlist = parse_envlist(env, &envc);
+        if (envlist == NULL) {
+            goto exit;
+        }
     }
 
     if (file_actions != NULL && file_actions != Py_None) {
@@ -7210,7 +7214,7 @@ exit:
     if (attrp) {
         (void)posix_spawnattr_destroy(attrp);
     }
-    if (envlist) {
+    if (envlist && envlist != environ) {
         free_string_array(envlist, envc);
     }
     if (argvlist) {