diff options
author | Eric Snow <ericsnowcurrently@gmail.com> | 2017-09-05 18:26:16 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-05 18:26:16 -0700 |
commit | 76d5abc8684bac4f2fc7cccfe2cd940923357351 (patch) | |
tree | 4ae6a3bd88bef1266a8d9723c589f925d90bf848 /Python/pylifecycle.c | |
parent | 501b324d3a940d26e0021a38aae8d896a30fbcff (diff) | |
download | cpython-git-76d5abc8684bac4f2fc7cccfe2cd940923357351.tar.gz |
bpo-30860: Consolidate stateful runtime globals. (#2594)
* 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).
Diffstat (limited to 'Python/pylifecycle.c')
-rw-r--r-- | Python/pylifecycle.c | 88 |
1 files changed, 57 insertions, 31 deletions
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 662405bdeb..f33e920e6b 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -77,6 +77,30 @@ extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *); extern void _PyGILState_Fini(void); #endif /* WITH_THREAD */ +_PyRuntimeState _PyRuntime = {}; + +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); +} + /* Global configuration variable declarations are in pydebug.h */ /* XXX (ncoghlan): move those declarations to pylifecycle.h? */ int Py_DebugFlag; /* Needed by parser.c */ @@ -100,8 +124,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 */ @@ -119,19 +141,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 @@ -544,14 +564,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"); } @@ -564,7 +586,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 @@ -606,7 +635,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"); @@ -698,7 +727,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 @@ -739,10 +768,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"); } @@ -763,7 +792,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 */ @@ -808,7 +837,7 @@ int _Py_InitializeMainInterpreter(const _PyMainInterpreterConfig *config) Py_XDECREF(warnings_module); } - _Py_Initialized = 1; + _PyRuntime.initialized = 1; if (!Py_NoSiteFlag) initsite(); /* Module site */ @@ -924,7 +953,7 @@ Py_FinalizeEx(void) PyThreadState *tstate; int status = 0; - if (!_Py_Initialized) + if (!_PyRuntime.initialized) return status; wait_for_thread_shutdown(); @@ -946,9 +975,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) { @@ -1110,6 +1139,7 @@ Py_FinalizeEx(void) #endif call_ll_exitfuncs(); + _PyRuntime_Finalize(); return status; } @@ -1139,7 +1169,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"); #ifdef WITH_THREAD @@ -1854,20 +1884,19 @@ exit: # include "pythread.h" #endif -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(); } @@ -1900,22 +1929,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); |