summaryrefslogtreecommitdiffstats
path: root/Modules/_posixsubprocess.c
diff options
context:
space:
mode:
authorGregory P. Smith <greg@krypto.org>2022-05-01 23:09:50 (GMT)
committerGitHub <noreply@github.com>2022-05-01 23:09:50 (GMT)
commitea1eba03e7e8401d5acf8b30b56b41faa209e8c6 (patch)
tree21d81eb6e2a87a1853e2fea2cd5d295574a2ec7e /Modules/_posixsubprocess.c
parente7de54321952ebb58cc414f2160c9ad4f6510af2 (diff)
downloadcpython-ea1eba03e7e8401d5acf8b30b56b41faa209e8c6.zip
cpython-ea1eba03e7e8401d5acf8b30b56b41faa209e8c6.tar.gz
cpython-ea1eba03e7e8401d5acf8b30b56b41faa209e8c6.tar.bz2
[3.10] gh-91401: Conservative backport of `subprocess._USE_VFORK` (#91932)
This does not alter the `_posixsubprocess.fork_exec()` private API to avoid issues for anyone relying on that (bad idea) or for anyone who's `subprocess.py` and `_posixsubprocess.so` upgrades may not become visible to existing Python 3.10 processes at the same time. Backports the concept of cd5726fe674eaff442510eeb6c75628858be9e9f. Provides a fail-safe way to disable vfork for #91401. I didn't backport the documentation as I don't actually expect this to be used and `.. versionadded: 3.10.5` always looks weird in docs. It's being done more to have a fail-safe in place for people just in case.
Diffstat (limited to 'Modules/_posixsubprocess.c')
-rw-r--r--Modules/_posixsubprocess.c27
1 files changed, 25 insertions, 2 deletions
diff --git a/Modules/_posixsubprocess.c b/Modules/_posixsubprocess.c
index 18a81c6..b852ad7 100644
--- a/Modules/_posixsubprocess.c
+++ b/Modules/_posixsubprocess.c
@@ -936,8 +936,31 @@ subprocess_fork_exec(PyObject *module, PyObject *args)
#ifdef VFORK_USABLE
/* Use vfork() only if it's safe. See the comment above child_exec(). */
sigset_t old_sigs;
- if (preexec_fn == Py_None &&
- !call_setuid && !call_setgid && !call_setgroups) {
+ int allow_vfork;
+ if (preexec_fn == Py_None) {
+ allow_vfork = 1; /* 3.10.0 behavior */
+ PyObject *subprocess_module = PyImport_ImportModule("subprocess");
+ if (subprocess_module != NULL) {
+ PyObject *allow_vfork_obj = PyObject_GetAttrString(
+ subprocess_module, "_USE_VFORK");
+ Py_DECREF(subprocess_module);
+ if (allow_vfork_obj != NULL) {
+ allow_vfork = PyObject_IsTrue(allow_vfork_obj);
+ Py_DECREF(allow_vfork_obj);
+ if (allow_vfork < 0) {
+ PyErr_Clear(); /* Bad _USE_VFORK attribute. */
+ allow_vfork = 1; /* 3.10.0 behavior */
+ }
+ } else {
+ PyErr_Clear(); /* No _USE_VFORK attribute. */
+ }
+ } else {
+ PyErr_Clear(); /* no subprocess module? suspicious; don't care. */
+ }
+ } else {
+ allow_vfork = 0;
+ }
+ if (allow_vfork && !call_setuid && !call_setgid && !call_setgroups) {
/* Block all signals to ensure that no signal handlers are run in the
* child process while it shares memory with us. Note that signals
* used internally by C libraries won't be blocked by