mirror of
https://github.com/python/cpython.git
synced 2025-11-02 03:01:58 +00:00
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.)
This commit is contained in:
parent
24c56b4642
commit
f32369480d
21 changed files with 295 additions and 39 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 **
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue