diff options
author | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
---|---|---|
committer | shadchin <shadchin@yandex-team.ru> | 2022-04-18 12:39:32 +0300 |
commit | d4be68e361f4258cf0848fc70018dfe37a2acc24 (patch) | |
tree | 153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Python/pystate.c | |
parent | 260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff) | |
download | ydb-d4be68e361f4258cf0848fc70018dfe37a2acc24.tar.gz |
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Python/pystate.c')
-rw-r--r-- | contrib/tools/python3/src/Python/pystate.c | 272 |
1 files changed, 208 insertions, 64 deletions
diff --git a/contrib/tools/python3/src/Python/pystate.c b/contrib/tools/python3/src/Python/pystate.c index c3520c336a..df98eb11bb 100644 --- a/contrib/tools/python3/src/Python/pystate.c +++ b/contrib/tools/python3/src/Python/pystate.c @@ -4,6 +4,7 @@ #include "Python.h" #include "pycore_ceval.h" #include "pycore_initconfig.h" +#include "pycore_object.h" // _PyType_InitCache() #include "pycore_pyerrors.h" #include "pycore_pylifecycle.h" #include "pycore_pymem.h" // _PyMem_SetDefaultAllocator() @@ -53,6 +54,9 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) void *open_code_hook = runtime->open_code_hook; void *open_code_userdata = runtime->open_code_userdata; _Py_AuditHookEntry *audit_hook_head = runtime->audit_hook_head; + // bpo-42882: Preserve next_index value if Py_Initialize()/Py_Finalize() + // is called multiple times. + Py_ssize_t unicode_next_index = runtime->unicode_ids.next_index; memset(runtime, 0, sizeof(*runtime)); @@ -73,18 +77,24 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime) runtime->interpreters.mutex = PyThread_allocate_lock(); if (runtime->interpreters.mutex == NULL) { - return _PyStatus_ERR("Can't initialize threads for interpreter"); + return _PyStatus_NO_MEMORY(); } runtime->interpreters.next_id = -1; runtime->xidregistry.mutex = PyThread_allocate_lock(); if (runtime->xidregistry.mutex == NULL) { - return _PyStatus_ERR("Can't initialize threads for cross-interpreter data registry"); + return _PyStatus_NO_MEMORY(); } // Set it to the ID of the main thread of the main interpreter. runtime->main_thread = PyThread_get_thread_ident(); + runtime->unicode_ids.lock = PyThread_allocate_lock(); + if (runtime->unicode_ids.lock == NULL) { + return _PyStatus_NO_MEMORY(); + } + runtime->unicode_ids.next_index = unicode_next_index; + return _PyStatus_OK(); } @@ -108,26 +118,24 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime) /* Force the allocator used by _PyRuntimeState_Init(). */ PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - - if (runtime->interpreters.mutex != NULL) { - PyThread_free_lock(runtime->interpreters.mutex); - runtime->interpreters.mutex = NULL; +#define FREE_LOCK(LOCK) \ + if (LOCK != NULL) { \ + PyThread_free_lock(LOCK); \ + LOCK = NULL; \ } - if (runtime->xidregistry.mutex != NULL) { - PyThread_free_lock(runtime->xidregistry.mutex); - runtime->xidregistry.mutex = NULL; - } + FREE_LOCK(runtime->interpreters.mutex); + FREE_LOCK(runtime->xidregistry.mutex); + FREE_LOCK(runtime->unicode_ids.lock); +#undef FREE_LOCK PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); } #ifdef HAVE_FORK /* This function is called from PyOS_AfterFork_Child to ensure that - * newly created child processes do not share locks with the parent. - */ - -void + newly created child processes do not share locks with the parent. */ +PyStatus _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) { // This was initially set in _PyRuntimeState_Init(). @@ -138,26 +146,25 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime) PyMemAllocatorEx old_alloc; _PyMem_SetDefaultAllocator(PYMEM_DOMAIN_RAW, &old_alloc); - int interp_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); - int xidregistry_mutex = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); + int reinit_interp = _PyThread_at_fork_reinit(&runtime->interpreters.mutex); + int reinit_xidregistry = _PyThread_at_fork_reinit(&runtime->xidregistry.mutex); + int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_ids.lock); PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc); /* bpo-42540: id_mutex is freed by _PyInterpreterState_Delete, which does * not force the default allocator. */ - int main_interp_id_mutex = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); + int reinit_main_id = _PyThread_at_fork_reinit(&runtime->interpreters.main->id_mutex); - if (interp_mutex < 0) { - Py_FatalError("Can't initialize lock for runtime interpreters"); - } - - if (main_interp_id_mutex < 0) { - Py_FatalError("Can't initialize ID lock for main interpreter"); - } + if (reinit_interp < 0 + || reinit_main_id < 0 + || reinit_xidregistry < 0 + || reinit_unicode_ids < 0) + { + return _PyStatus_ERR("Failed to reinitialize runtime locks"); - if (xidregistry_mutex < 0) { - Py_FatalError("Can't initialize lock for cross-interpreter data registry"); } + return _PyStatus_OK(); } #endif @@ -223,6 +230,7 @@ PyInterpreterState_New(void) _PyGC_InitState(&interp->gc); PyConfig_InitPythonConfig(&interp->config); + _PyType_InitCache(interp); interp->eval_frame = _PyEval_EvalFrameDefault; #ifdef HAVE_DLOPEN @@ -276,14 +284,11 @@ out_of_memory: } -void -PyInterpreterState_Clear(PyInterpreterState *interp) +static void +interpreter_clear(PyInterpreterState *interp, PyThreadState *tstate) { _PyRuntimeState *runtime = interp->runtime; - /* Use the current Python thread state to call audit hooks, - not the current Python thread state of 'interp'. */ - PyThreadState *tstate = _PyThreadState_GET(); if (_PySys_Audit(tstate, "cpython.PyInterpreterState_Clear", NULL) < 0) { _PyErr_Clear(tstate); } @@ -302,8 +307,6 @@ PyInterpreterState_Clear(PyInterpreterState *interp) Py_CLEAR(interp->codec_error_registry); Py_CLEAR(interp->modules); Py_CLEAR(interp->modules_by_index); - Py_CLEAR(interp->sysdict); - Py_CLEAR(interp->builtins); Py_CLEAR(interp->builtins_copy); Py_CLEAR(interp->importlib); Py_CLEAR(interp->import_func); @@ -313,15 +316,52 @@ PyInterpreterState_Clear(PyInterpreterState *interp) Py_CLEAR(interp->after_forkers_parent); Py_CLEAR(interp->after_forkers_child); #endif - if (_PyRuntimeState_GetFinalizing(runtime) == NULL) { - _PyWarnings_Fini(interp); - } + + _PyAST_Fini(interp); + _PyWarnings_Fini(interp); + _PyAtExit_Fini(interp); + + // All Python types must be destroyed before the last GC collection. Python + // types create a reference cycle to themselves in their in their + // PyTypeObject.tp_mro member (the tuple contains the type). + + /* Last garbage collection on this interpreter */ + _PyGC_CollectNoFail(tstate); + _PyGC_Fini(interp); + + /* We don't clear sysdict and builtins until the end of this function. + Because clearing other attributes can execute arbitrary Python code + which requires sysdict and builtins. */ + PyDict_Clear(interp->sysdict); + PyDict_Clear(interp->builtins); + Py_CLEAR(interp->sysdict); + Py_CLEAR(interp->builtins); + // XXX Once we have one allocator per interpreter (i.e. // per-interpreter GC) we must ensure that all of the interpreter's // objects have been cleaned up at the point. } +void +PyInterpreterState_Clear(PyInterpreterState *interp) +{ + // Use the current Python thread state to call audit hooks and to collect + // garbage. It can be different than the current Python thread state + // of 'interp'. + PyThreadState *current_tstate = _PyThreadState_GET(); + + interpreter_clear(interp, current_tstate); +} + + +void +_PyInterpreterState_Clear(PyThreadState *tstate) +{ + interpreter_clear(tstate->interp, tstate); +} + + static void zapthreads(PyInterpreterState *interp, int check_current) { @@ -376,11 +416,12 @@ PyInterpreterState_Delete(PyInterpreterState *interp) } +#ifdef HAVE_FORK /* * Delete all interpreter states except the main interpreter. If there * is a current interpreter state, it *must* be the main interpreter. */ -void +PyStatus _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) { struct _gilstate_runtime_state *gilstate = &runtime->gilstate; @@ -388,7 +429,7 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) PyThreadState *tstate = _PyThreadState_Swap(gilstate, NULL); if (tstate != NULL && tstate->interp != interpreters->main) { - Py_FatalError("not main interpreter"); + return _PyStatus_ERR("not main interpreter"); } HEAD_LOCK(runtime); @@ -414,10 +455,12 @@ _PyInterpreterState_DeleteExceptMain(_PyRuntimeState *runtime) HEAD_UNLOCK(runtime); if (interpreters->head == NULL) { - Py_FatalError("missing main interpreter"); + return _PyStatus_ERR("missing main interpreter"); } _PyThreadState_Swap(gilstate, tstate); + return _PyStatus_OK(); } +#endif PyInterpreterState * @@ -496,24 +539,25 @@ _PyInterpreterState_IDInitref(PyInterpreterState *interp) } -void +int _PyInterpreterState_IDIncref(PyInterpreterState *interp) { - if (interp->id_mutex == NULL) { - return; + if (_PyInterpreterState_IDInitref(interp) < 0) { + return -1; } + PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); interp->id_refcount += 1; PyThread_release_lock(interp->id_mutex); + return 0; } void _PyInterpreterState_IDDecref(PyInterpreterState *interp) { - if (interp->id_mutex == NULL) { - return; - } + assert(interp->id_mutex != NULL); + struct _gilstate_runtime_state *gilstate = &_PyRuntime.gilstate; PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); assert(interp->id_refcount != 0); @@ -579,11 +623,11 @@ new_threadstate(PyInterpreterState *interp, int init) tstate->frame = NULL; tstate->recursion_depth = 0; - tstate->overflowed = 0; - tstate->recursion_critical = 0; + tstate->recursion_headroom = 0; tstate->stackcheck_counter = 0; tstate->tracing = 0; - tstate->use_tracing = 0; + tstate->root_cframe.use_tracing = 0; + tstate->cframe = &tstate->root_cframe; tstate->gilstate_counter = 0; tstate->async_exc = NULL; tstate->thread_id = PyThread_get_thread_ident(); @@ -753,7 +797,7 @@ PyState_RemoveModule(struct PyModuleDef* def) return PyList_SetItem(interp->modules_by_index, index, Py_None); } -/* Used by PyImport_Cleanup() */ +// Used by finalize_modules() void _PyInterpreterState_ClearModules(PyInterpreterState *interp) { @@ -949,6 +993,14 @@ _PyThreadState_DeleteExcept(_PyRuntimeState *runtime, PyThreadState *tstate) } +#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS +PyThreadState* +_PyThreadState_GetTSS(void) { + return PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey); +} +#endif + + PyThreadState * _PyThreadState_UncheckedGet(void) { @@ -968,7 +1020,11 @@ PyThreadState_Get(void) PyThreadState * _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *newts) { +#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS + PyThreadState *oldts = _PyThreadState_GetTSS(); +#else PyThreadState *oldts = _PyRuntimeGILState_GetThreadState(gilstate); +#endif _PyRuntimeGILState_SetThreadState(gilstate, newts); /* It should not be possible for more than one thread state @@ -987,6 +1043,9 @@ _PyThreadState_Swap(struct _gilstate_runtime_state *gilstate, PyThreadState *new errno = err; } #endif +#ifdef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS + PyThread_tss_set(&gilstate->autoTSSkey, newts); +#endif return oldts; } @@ -1092,7 +1151,7 @@ PyThreadState_SetAsyncExc(unsigned long id, PyObject *exc) HEAD_UNLOCK(runtime); Py_XDECREF(old_exc); - _PyEval_SignalAsyncExc(tstate); + _PyEval_SignalAsyncExc(tstate->interp); return 1; } HEAD_UNLOCK(runtime); @@ -1185,6 +1244,69 @@ done: return result; } +PyObject * +_PyThread_CurrentExceptions(void) +{ + PyThreadState *tstate = _PyThreadState_GET(); + + _Py_EnsureTstateNotNULL(tstate); + + if (_PySys_Audit(tstate, "sys._current_exceptions", NULL) < 0) { + return NULL; + } + + PyObject *result = PyDict_New(); + if (result == NULL) { + return NULL; + } + + /* for i in all interpreters: + * for t in all of i's thread states: + * if t's frame isn't NULL, map t's id to its frame + * Because these lists can mutate even when the GIL is held, we + * need to grab head_mutex for the duration. + */ + _PyRuntimeState *runtime = tstate->interp->runtime; + HEAD_LOCK(runtime); + PyInterpreterState *i; + for (i = runtime->interpreters.head; i != NULL; i = i->next) { + PyThreadState *t; + for (t = i->tstate_head; t != NULL; t = t->next) { + _PyErr_StackItem *err_info = _PyErr_GetTopmostException(t); + if (err_info == NULL) { + continue; + } + PyObject *id = PyLong_FromUnsignedLong(t->thread_id); + if (id == NULL) { + goto fail; + } + PyObject *exc_info = PyTuple_Pack( + 3, + err_info->exc_type != NULL ? err_info->exc_type : Py_None, + err_info->exc_value != NULL ? err_info->exc_value : Py_None, + err_info->exc_traceback != NULL ? err_info->exc_traceback : Py_None); + if (exc_info == NULL) { + Py_DECREF(id); + goto fail; + } + int stat = PyDict_SetItem(result, id, exc_info); + Py_DECREF(id); + Py_DECREF(exc_info); + if (stat < 0) { + goto fail; + } + } + } + goto done; + +fail: + Py_CLEAR(result); + +done: + HEAD_UNLOCK(runtime); + return result; +} + /* Python "auto thread state" API. */ /* Keep this as a static, as it is not reliable! It can only @@ -1208,9 +1330,23 @@ PyThreadState_IsCurrent(PyThreadState *tstate) Py_Initialize/Py_FinalizeEx */ PyStatus -_PyGILState_Init(PyThreadState *tstate) +_PyGILState_Init(_PyRuntimeState *runtime) +{ + struct _gilstate_runtime_state *gilstate = &runtime->gilstate; + if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { + return _PyStatus_NO_MEMORY(); + } + // PyThreadState_New() calls _PyGILState_NoteThreadState() which does + // nothing before autoInterpreterState is set. + assert(gilstate->autoInterpreterState == NULL); + return _PyStatus_OK(); +} + + +PyStatus +_PyGILState_SetTstate(PyThreadState *tstate) { - if (!_Py_IsMainInterpreter(tstate)) { + if (!_Py_IsMainInterpreter(tstate->interp)) { /* Currently, PyGILState is shared by all interpreters. The main * interpreter is responsible to initialize it. */ return _PyStatus_OK(); @@ -1222,9 +1358,6 @@ _PyGILState_Init(PyThreadState *tstate) struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; - if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { - return _PyStatus_NO_MEMORY(); - } gilstate->autoInterpreterState = tstate->interp; assert(PyThread_tss_get(&gilstate->autoTSSkey) == NULL); assert(tstate->gilstate_counter == 0); @@ -1240,18 +1373,19 @@ _PyGILState_GetInterpreterStateUnsafe(void) } void -_PyGILState_Fini(PyThreadState *tstate) +_PyGILState_Fini(PyInterpreterState *interp) { - struct _gilstate_runtime_state *gilstate = &tstate->interp->runtime->gilstate; + struct _gilstate_runtime_state *gilstate = &interp->runtime->gilstate; PyThread_tss_delete(&gilstate->autoTSSkey); gilstate->autoInterpreterState = NULL; } +#ifdef HAVE_FORK /* Reset the TSS key - called by PyOS_AfterFork_Child(). * This should not be necessary, but some - buggy - pthread implementations * don't reset TSS upon fork(), see issue #10517. */ -void +PyStatus _PyGILState_Reinit(_PyRuntimeState *runtime) { struct _gilstate_runtime_state *gilstate = &runtime->gilstate; @@ -1259,7 +1393,7 @@ _PyGILState_Reinit(_PyRuntimeState *runtime) PyThread_tss_delete(&gilstate->autoTSSkey); if (PyThread_tss_create(&gilstate->autoTSSkey) != 0) { - Py_FatalError("Could not allocate TSS entry"); + return _PyStatus_NO_MEMORY(); } /* If the thread had an associated auto thread state, reassociate it with @@ -1267,9 +1401,11 @@ _PyGILState_Reinit(_PyRuntimeState *runtime) if (tstate && PyThread_tss_set(&gilstate->autoTSSkey, (void *)tstate) != 0) { - Py_FatalError("Couldn't create autoTSSkey mapping"); + return _PyStatus_ERR("failed to set autoTSSkey"); } + return _PyStatus_OK(); } +#endif /* When a thread state is created for a thread by some mechanism other than PyGILState_Ensure, it's important that the GILState machinery knows about @@ -1356,7 +1492,9 @@ PyGILState_Ensure(void) /* Ensure that _PyEval_InitThreads() and _PyGILState_Init() have been called by Py_Initialize() */ +#ifndef EXPERIMENTAL_ISOLATED_SUBINTERPRETERS assert(_PyEval_ThreadsInitialized(runtime)); +#endif assert(gilstate->autoInterpreterState); PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(&gilstate->autoTSSkey); @@ -1812,11 +1950,17 @@ _PyInterpreterState_GetConfig(PyInterpreterState *interp) } -PyStatus -_PyInterpreterState_SetConfig(PyInterpreterState *interp, - const PyConfig *config) +int +_PyInterpreterState_GetConfigCopy(PyConfig *config) { - return _PyConfig_Copy(&interp->config, config); + PyInterpreterState *interp = PyInterpreterState_Get(); + + PyStatus status = _PyConfig_Copy(config, &interp->config); + if (PyStatus_Exception(status)) { + _PyErr_SetFromPyStatus(status); + return -1; + } + return 0; } |