summaryrefslogtreecommitdiffstats
path: root/Python/pylifecycle.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-05-06 21:59:30 (GMT)
committerGitHub <noreply@github.com>2023-05-06 21:59:30 (GMT)
commit92d8bfffbf377e91d8b92666525cb8700bb1d5e8 (patch)
treefacb90810c394cba63d50feef6fa7aaebd45f947 /Python/pylifecycle.c
parentfff193bbfebe7b00229856b1e8105ab3de36437f (diff)
downloadcpython-92d8bfffbf377e91d8b92666525cb8700bb1d5e8.zip
cpython-92d8bfffbf377e91d8b92666525cb8700bb1d5e8.tar.gz
cpython-92d8bfffbf377e91d8b92666525cb8700bb1d5e8.tar.bz2
gh-99113: Make Sure the GIL is Acquired at the Right Places (gh-104208)
This is a pre-requisite for a per-interpreter GIL. Without it this change isn't strictly necessary. However, there is no real downside otherwise.
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r--Python/pylifecycle.c25
1 files changed, 22 insertions, 3 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 7057086..61f87c5 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -591,6 +591,7 @@ init_interp_create_gil(PyThreadState *tstate, int own_gil)
/* finalize_interp_delete() comment explains why _PyEval_FiniGIL() is
only called here. */
+ // XXX This is broken with a per-interpreter GIL.
_PyEval_FiniGIL(tstate->interp);
/* Auto-thread-state API */
@@ -645,7 +646,8 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
return _PyStatus_ERR("can't make first thread");
}
_PyThreadState_Bind(tstate);
- (void) PyThreadState_Swap(tstate);
+ // XXX For now we do this before the GIL is created.
+ (void) _PyThreadState_SwapNoGIL(tstate);
status = init_interp_create_gil(tstate, config.own_gil);
if (_PyStatus_EXCEPTION(status)) {
@@ -2025,11 +2027,20 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
}
_PyThreadState_Bind(tstate);
- PyThreadState *save_tstate = PyThreadState_Swap(tstate);
+ // XXX For now we do this before the GIL is created.
+ PyThreadState *save_tstate = _PyThreadState_SwapNoGIL(tstate);
+ int has_gil = 0;
+
+ /* From this point until the init_interp_create_gil() call,
+ we must not do anything that requires that the GIL be held
+ (or otherwise exist). That applies whether or not the new
+ interpreter has its own GIL (e.g. the main interpreter). */
/* Copy the current interpreter config into the new interpreter */
const PyConfig *src_config;
if (save_tstate != NULL) {
+ // XXX Might new_interpreter() have been called without the GIL held?
+ _PyEval_ReleaseLock(save_tstate);
src_config = _PyInterpreterState_GetConfig(save_tstate->interp);
}
else
@@ -2039,11 +2050,13 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
src_config = _PyInterpreterState_GetConfig(main_interp);
}
+ /* This does not require that the GIL be held. */
status = _PyConfig_Copy(&interp->config, src_config);
if (_PyStatus_EXCEPTION(status)) {
goto error;
}
+ /* This does not require that the GIL be held. */
status = init_interp_settings(interp, config);
if (_PyStatus_EXCEPTION(status)) {
goto error;
@@ -2053,6 +2066,7 @@ new_interpreter(PyThreadState **tstate_p, const PyInterpreterConfig *config)
if (_PyStatus_EXCEPTION(status)) {
goto error;
}
+ has_gil = 1;
status = pycore_interp_init(tstate);
if (_PyStatus_EXCEPTION(status)) {
@@ -2072,7 +2086,12 @@ error:
/* Oops, it didn't work. Undo it all. */
PyErr_PrintEx(0);
- PyThreadState_Swap(save_tstate);
+ if (has_gil) {
+ PyThreadState_Swap(save_tstate);
+ }
+ else {
+ _PyThreadState_SwapNoGIL(save_tstate);
+ }
PyThreadState_Clear(tstate);
PyThreadState_Delete(tstate);
PyInterpreterState_Delete(interp);