diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2022-10-26 17:16:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-26 17:16:30 (GMT) |
commit | f32369480df54cb06884537ef16cb5a4143393f0 (patch) | |
tree | de906b0a7decf4c16d94d5311674ba19c278f9af /Python | |
parent | 24c56b4642d467c194c57188d4a3b1848ee444c2 (diff) | |
download | cpython-f32369480df54cb06884537ef16cb5a4143393f0.zip cpython-f32369480df54cb06884537ef16cb5a4143393f0.tar.gz cpython-f32369480df54cb06884537ef16cb5a4143393f0.tar.bz2 |
gh-98608: Change _Py_NewInterpreter() to _Py_NewInterpreterFromConfig() (gh-98609)
(see https://github.com/python/cpython/issues/98608)
This change does the following:
1. change the argument to a new `_PyInterpreterConfig` struct
2. rename the function to `_Py_NewInterpreterFromConfig()`, inspired by `Py_InitializeFromConfig()` (takes a `_PyInterpreterConfig` instead of `isolated_subinterpreter`)
3. split up the boolean `isolated_subinterpreter` into the corresponding multiple granular settings
* allow_fork
* allow_subprocess
* allow_threads
4. add `PyInterpreterState.feature_flags` to store those settings
5. add a function for checking if a feature is enabled on an opaque `PyInterpreterState *`
6. drop `PyConfig._isolated_interpreter`
The existing default (see `Py_NewInterpeter()` and `Py_Initialize*()`) allows fork, subprocess, and threads and the optional "isolated" interpreter (see the `_xxsubinterpreters` module) disables all three. None of that changes here; the defaults are preserved.
Note that the given `_PyInterpreterConfig` will not be used outside `_Py_NewInterpreterFromConfig()`, nor preserved. This contrasts with how `PyConfig` is currently preserved, used, and even modified outside `Py_InitializeFromConfig()`. I'd rather just avoid that mess from the start for `_PyInterpreterConfig`. We can preserve it later if we find an actual need.
This change allows us to follow up with a number of improvements (e.g. stop disallowing subprocess and support disallowing exec instead).
(Note that this PR adds "private" symbols. We'll probably make them public, and add docs, in a separate change.)
Diffstat (limited to 'Python')
-rw-r--r-- | Python/initconfig.c | 4 | ||||
-rw-r--r-- | Python/pylifecycle.c | 45 | ||||
-rw-r--r-- | Python/pystate.c | 8 |
3 files changed, 40 insertions, 17 deletions
diff --git a/Python/initconfig.c b/Python/initconfig.c index bbc2ebb..4b78429 100644 --- a/Python/initconfig.c +++ b/Python/initconfig.c @@ -780,7 +780,6 @@ _PyConfig_InitCompatConfig(PyConfig *config) config->check_hash_pycs_mode = NULL; config->pathconfig_warnings = -1; config->_init_main = 1; - config->_isolated_interpreter = 0; #ifdef MS_WINDOWS config->legacy_windows_stdio = -1; #endif @@ -1015,7 +1014,6 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2) COPY_WSTR_ATTR(check_hash_pycs_mode); COPY_ATTR(pathconfig_warnings); COPY_ATTR(_init_main); - COPY_ATTR(_isolated_interpreter); COPY_ATTR(use_frozen_modules); COPY_ATTR(safe_path); COPY_WSTRLIST(orig_argv); @@ -1123,7 +1121,6 @@ _PyConfig_AsDict(const PyConfig *config) SET_ITEM_WSTR(check_hash_pycs_mode); SET_ITEM_INT(pathconfig_warnings); SET_ITEM_INT(_init_main); - SET_ITEM_INT(_isolated_interpreter); SET_ITEM_WSTRLIST(orig_argv); SET_ITEM_INT(use_frozen_modules); SET_ITEM_INT(safe_path); @@ -1418,7 +1415,6 @@ _PyConfig_FromDict(PyConfig *config, PyObject *dict) GET_UINT(_install_importlib); GET_UINT(_init_main); - GET_UINT(_isolated_interpreter); GET_UINT(use_frozen_modules); GET_UINT(safe_path); GET_UINT(_is_python_build); diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 4195a9d..334abfb 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -611,6 +611,22 @@ pycore_init_runtime(_PyRuntimeState *runtime, } +static void +init_interp_settings(PyInterpreterState *interp, const _PyInterpreterConfig *config) +{ + assert(interp->feature_flags == 0); + if (config->allow_fork) { + interp->feature_flags |= Py_RTFLAGS_FORK; + } + if (config->allow_subprocess) { + interp->feature_flags |= Py_RTFLAGS_SUBPROCESS; + } + if (config->allow_threads) { + interp->feature_flags |= Py_RTFLAGS_THREADS; + } +} + + static PyStatus init_interp_create_gil(PyThreadState *tstate) { @@ -638,7 +654,7 @@ init_interp_create_gil(PyThreadState *tstate) static PyStatus pycore_create_interpreter(_PyRuntimeState *runtime, - const PyConfig *config, + const PyConfig *src_config, PyThreadState **tstate_p) { /* Auto-thread-state API */ @@ -653,11 +669,14 @@ pycore_create_interpreter(_PyRuntimeState *runtime, } assert(_Py_IsMainInterpreter(interp)); - status = _PyConfig_Copy(&interp->config, config); + status = _PyConfig_Copy(&interp->config, src_config); if (_PyStatus_EXCEPTION(status)) { return status; } + const _PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT; + init_interp_settings(interp, &config); + PyThreadState *tstate = PyThreadState_New(interp); if (tstate == NULL) { return _PyStatus_ERR("can't make first thread"); @@ -1961,7 +1980,7 @@ Py_Finalize(void) */ static PyStatus -new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter) +new_interpreter(PyThreadState **tstate_p, const _PyInterpreterConfig *config) { PyStatus status; @@ -1995,23 +2014,23 @@ new_interpreter(PyThreadState **tstate_p, int isolated_subinterpreter) PyThreadState *save_tstate = PyThreadState_Swap(tstate); /* Copy the current interpreter config into the new interpreter */ - const PyConfig *config; + const PyConfig *src_config; if (save_tstate != NULL) { - config = _PyInterpreterState_GetConfig(save_tstate->interp); + src_config = _PyInterpreterState_GetConfig(save_tstate->interp); } else { /* No current thread state, copy from the main interpreter */ PyInterpreterState *main_interp = _PyInterpreterState_Main(); - config = _PyInterpreterState_GetConfig(main_interp); + src_config = _PyInterpreterState_GetConfig(main_interp); } - - status = _PyConfig_Copy(&interp->config, config); + status = _PyConfig_Copy(&interp->config, src_config); if (_PyStatus_EXCEPTION(status)) { goto error; } - interp->config._isolated_interpreter = isolated_subinterpreter; + + init_interp_settings(interp, config); status = init_interp_create_gil(tstate); if (_PyStatus_EXCEPTION(status)) { @@ -2045,21 +2064,21 @@ error: } PyThreadState * -_Py_NewInterpreter(int isolated_subinterpreter) +_Py_NewInterpreterFromConfig(const _PyInterpreterConfig *config) { PyThreadState *tstate = NULL; - PyStatus status = new_interpreter(&tstate, isolated_subinterpreter); + PyStatus status = new_interpreter(&tstate, config); if (_PyStatus_EXCEPTION(status)) { Py_ExitStatusException(status); } return tstate; - } PyThreadState * Py_NewInterpreter(void) { - return _Py_NewInterpreter(0); + const _PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT; + return _Py_NewInterpreterFromConfig(&config); } /* Delete an interpreter and its last thread. This requires that the diff --git a/Python/pystate.c b/Python/pystate.c index c74868d..dd6d6e9 100644 --- a/Python/pystate.c +++ b/Python/pystate.c @@ -2177,6 +2177,14 @@ _Py_GetConfig(void) return _PyInterpreterState_GetConfig(tstate->interp); } + +int +_PyInterpreterState_HasFeature(PyInterpreterState *interp, unsigned long feature) +{ + return ((interp->feature_flags & feature) != 0); +} + + #define MINIMUM_OVERHEAD 1000 static PyObject ** |