mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
bpo-30860: Consolidate stateful runtime globals. (#3397)
* group the (stateful) runtime globals into various topical structs * consolidate the topical structs under a single top-level _PyRuntimeState struct * add a check-c-globals.py script that helps identify runtime globals Other globals are excluded (see globals.txt and check-c-globals.py).
This commit is contained in:
parent
bab21faded
commit
2ebc5ce42a
72 changed files with 2746 additions and 1312 deletions
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "Python-ast.h"
|
||||
#undef Yield /* undefine macro conflicting with winbase.h */
|
||||
#include "internal/pystate.h"
|
||||
#include "grammar.h"
|
||||
#include "node.h"
|
||||
#include "token.h"
|
||||
|
@ -75,6 +76,36 @@ extern void _Py_ReadyTypes(void);
|
|||
extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
|
||||
extern void _PyGILState_Fini(void);
|
||||
|
||||
_PyRuntimeState _PyRuntime = {0, 0};
|
||||
|
||||
void
|
||||
_PyRuntime_Initialize(void)
|
||||
{
|
||||
/* XXX We only initialize once in the process, which aligns with
|
||||
the static initialization of the former globals now found in
|
||||
_PyRuntime. However, _PyRuntime *should* be initialized with
|
||||
every Py_Initialize() call, but doing so breaks the runtime.
|
||||
This is because the runtime state is not properly finalized
|
||||
currently. */
|
||||
static int initialized = 0;
|
||||
if (initialized)
|
||||
return;
|
||||
initialized = 1;
|
||||
_PyRuntimeState_Init(&_PyRuntime);
|
||||
}
|
||||
|
||||
void
|
||||
_PyRuntime_Finalize(void)
|
||||
{
|
||||
_PyRuntimeState_Fini(&_PyRuntime);
|
||||
}
|
||||
|
||||
int
|
||||
_Py_IsFinalizing(void)
|
||||
{
|
||||
return _PyRuntime.finalizing != NULL;
|
||||
}
|
||||
|
||||
/* Global configuration variable declarations are in pydebug.h */
|
||||
/* XXX (ncoghlan): move those declarations to pylifecycle.h? */
|
||||
int Py_DebugFlag; /* Needed by parser.c */
|
||||
|
@ -98,8 +129,6 @@ int Py_LegacyWindowsFSEncodingFlag = 0; /* Uses mbcs instead of utf-8 */
|
|||
int Py_LegacyWindowsStdioFlag = 0; /* Uses FileIO instead of WindowsConsoleIO */
|
||||
#endif
|
||||
|
||||
PyThreadState *_Py_Finalizing = NULL;
|
||||
|
||||
/* Hack to force loading of object files */
|
||||
int (*_PyOS_mystrnicmp_hack)(const char *, const char *, Py_ssize_t) = \
|
||||
PyOS_mystrnicmp; /* Python/pystrcmp.o */
|
||||
|
@ -117,19 +146,17 @@ PyModule_GetWarningsModule(void)
|
|||
*
|
||||
* Can be called prior to Py_Initialize.
|
||||
*/
|
||||
int _Py_CoreInitialized = 0;
|
||||
int _Py_Initialized = 0;
|
||||
|
||||
int
|
||||
_Py_IsCoreInitialized(void)
|
||||
{
|
||||
return _Py_CoreInitialized;
|
||||
return _PyRuntime.core_initialized;
|
||||
}
|
||||
|
||||
int
|
||||
Py_IsInitialized(void)
|
||||
{
|
||||
return _Py_Initialized;
|
||||
return _PyRuntime.initialized;
|
||||
}
|
||||
|
||||
/* Helper to allow an embedding application to override the normal
|
||||
|
@ -542,14 +569,16 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
|
|||
_PyCoreConfig core_config = _PyCoreConfig_INIT;
|
||||
_PyMainInterpreterConfig preinit_config = _PyMainInterpreterConfig_INIT;
|
||||
|
||||
_PyRuntime_Initialize();
|
||||
|
||||
if (config != NULL) {
|
||||
core_config = *config;
|
||||
}
|
||||
|
||||
if (_Py_Initialized) {
|
||||
if (_PyRuntime.initialized) {
|
||||
Py_FatalError("Py_InitializeCore: main interpreter already initialized");
|
||||
}
|
||||
if (_Py_CoreInitialized) {
|
||||
if (_PyRuntime.core_initialized) {
|
||||
Py_FatalError("Py_InitializeCore: runtime core already initialized");
|
||||
}
|
||||
|
||||
|
@ -562,7 +591,14 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
|
|||
* threads still hanging around from a previous Py_Initialize/Finalize
|
||||
* pair :(
|
||||
*/
|
||||
_Py_Finalizing = NULL;
|
||||
_PyRuntime.finalizing = NULL;
|
||||
|
||||
if (_PyMem_SetupAllocators(core_config.allocator) < 0) {
|
||||
fprintf(stderr,
|
||||
"Error in PYTHONMALLOC: unknown allocator \"%s\"!\n",
|
||||
core_config.allocator);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
/* Passing "" to setlocale() on Android requests the C locale rather
|
||||
|
@ -604,7 +640,7 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
|
|||
Py_HashRandomizationFlag = 1;
|
||||
}
|
||||
|
||||
_PyInterpreterState_Init();
|
||||
_PyInterpreterState_Enable(&_PyRuntime);
|
||||
interp = PyInterpreterState_New();
|
||||
if (interp == NULL)
|
||||
Py_FatalError("Py_InitializeCore: can't make main interpreter");
|
||||
|
@ -694,7 +730,7 @@ void _Py_InitializeCore(const _PyCoreConfig *config)
|
|||
}
|
||||
|
||||
/* Only when we get here is the runtime core fully initialized */
|
||||
_Py_CoreInitialized = 1;
|
||||
_PyRuntime.core_initialized = 1;
|
||||
}
|
||||
|
||||
/* Read configuration settings from standard locations
|
||||
|
@ -735,10 +771,10 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
|||
PyInterpreterState *interp;
|
||||
PyThreadState *tstate;
|
||||
|
||||
if (!_Py_CoreInitialized) {
|
||||
if (!_PyRuntime.core_initialized) {
|
||||
Py_FatalError("Py_InitializeMainInterpreter: runtime core not initialized");
|
||||
}
|
||||
if (_Py_Initialized) {
|
||||
if (_PyRuntime.initialized) {
|
||||
Py_FatalError("Py_InitializeMainInterpreter: main interpreter already initialized");
|
||||
}
|
||||
|
||||
|
@ -759,7 +795,7 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
|||
* This means anything which needs support from extension modules
|
||||
* or pure Python code in the standard library won't work.
|
||||
*/
|
||||
_Py_Initialized = 1;
|
||||
_PyRuntime.initialized = 1;
|
||||
return 0;
|
||||
}
|
||||
/* TODO: Report exceptions rather than fatal errors below here */
|
||||
|
@ -804,7 +840,7 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config)
|
|||
Py_XDECREF(warnings_module);
|
||||
}
|
||||
|
||||
_Py_Initialized = 1;
|
||||
_PyRuntime.initialized = 1;
|
||||
|
||||
if (!Py_NoSiteFlag)
|
||||
initsite(); /* Module site */
|
||||
|
@ -920,7 +956,7 @@ Py_FinalizeEx(void)
|
|||
PyThreadState *tstate;
|
||||
int status = 0;
|
||||
|
||||
if (!_Py_Initialized)
|
||||
if (!_PyRuntime.initialized)
|
||||
return status;
|
||||
|
||||
wait_for_thread_shutdown();
|
||||
|
@ -942,9 +978,9 @@ Py_FinalizeEx(void)
|
|||
|
||||
/* Remaining threads (e.g. daemon threads) will automatically exit
|
||||
after taking the GIL (in PyEval_RestoreThread()). */
|
||||
_Py_Finalizing = tstate;
|
||||
_Py_Initialized = 0;
|
||||
_Py_CoreInitialized = 0;
|
||||
_PyRuntime.finalizing = tstate;
|
||||
_PyRuntime.initialized = 0;
|
||||
_PyRuntime.core_initialized = 0;
|
||||
|
||||
/* Flush sys.stdout and sys.stderr */
|
||||
if (flush_std_files() < 0) {
|
||||
|
@ -1104,6 +1140,7 @@ Py_FinalizeEx(void)
|
|||
#endif
|
||||
|
||||
call_ll_exitfuncs();
|
||||
_PyRuntime_Finalize();
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -1133,7 +1170,7 @@ Py_NewInterpreter(void)
|
|||
PyThreadState *tstate, *save_tstate;
|
||||
PyObject *bimod, *sysmod;
|
||||
|
||||
if (!_Py_Initialized)
|
||||
if (!_PyRuntime.initialized)
|
||||
Py_FatalError("Py_NewInterpreter: call Py_Initialize first");
|
||||
|
||||
/* Issue #10915, #15751: The GIL API doesn't work with multiple
|
||||
|
@ -1844,20 +1881,19 @@ exit:
|
|||
|
||||
# include "pythread.h"
|
||||
|
||||
static void (*pyexitfunc)(void) = NULL;
|
||||
/* For the atexit module. */
|
||||
void _Py_PyAtExit(void (*func)(void))
|
||||
{
|
||||
pyexitfunc = func;
|
||||
_PyRuntime.pyexitfunc = func;
|
||||
}
|
||||
|
||||
static void
|
||||
call_py_exitfuncs(void)
|
||||
{
|
||||
if (pyexitfunc == NULL)
|
||||
if (_PyRuntime.pyexitfunc == NULL)
|
||||
return;
|
||||
|
||||
(*pyexitfunc)();
|
||||
(*_PyRuntime.pyexitfunc)();
|
||||
PyErr_Clear();
|
||||
}
|
||||
|
||||
|
@ -1888,22 +1924,19 @@ wait_for_thread_shutdown(void)
|
|||
}
|
||||
|
||||
#define NEXITFUNCS 32
|
||||
static void (*exitfuncs[NEXITFUNCS])(void);
|
||||
static int nexitfuncs = 0;
|
||||
|
||||
int Py_AtExit(void (*func)(void))
|
||||
{
|
||||
if (nexitfuncs >= NEXITFUNCS)
|
||||
if (_PyRuntime.nexitfuncs >= NEXITFUNCS)
|
||||
return -1;
|
||||
exitfuncs[nexitfuncs++] = func;
|
||||
_PyRuntime.exitfuncs[_PyRuntime.nexitfuncs++] = func;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
call_ll_exitfuncs(void)
|
||||
{
|
||||
while (nexitfuncs > 0)
|
||||
(*exitfuncs[--nexitfuncs])();
|
||||
while (_PyRuntime.nexitfuncs > 0)
|
||||
(*_PyRuntime.exitfuncs[--_PyRuntime.nexitfuncs])();
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stderr);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue