[Python-checkins] gh-81057: Move More Globals in Core Code to _PyRuntimeState (gh-99516)

ericsnowcurrently webhook-mailer at python.org
Wed Nov 16 11:37:24 EST 2022


https://github.com/python/cpython/commit/5f55067e238c21de25f09ece9bb24ae8c42d02b4
commit: 5f55067e238c21de25f09ece9bb24ae8c42d02b4
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2022-11-16T09:37:14-07:00
summary:

gh-81057: Move More Globals in Core Code to _PyRuntimeState (gh-99516)

https://github.com/python/cpython/issues/81057

files:
M Include/cpython/modsupport.h
M Include/internal/pycore_fileutils.h
M Include/internal/pycore_floatobject.h
M Include/internal/pycore_import.h
M Include/internal/pycore_interp.h
M Include/internal/pycore_pyhash.h
M Include/internal/pycore_pylifecycle.h
M Include/internal/pycore_runtime.h
M Include/internal/pycore_runtime_init.h
M Include/internal/pycore_unicodeobject.h
M Modules/main.c
M Objects/floatobject.c
M Objects/moduleobject.c
M Objects/unicodeobject.c
M Python/bootstrap_hash.c
M Python/ceval_gil.c
M Python/fileutils.c
M Python/importdl.c
M Python/modsupport.c
M Python/pylifecycle.c
M Python/pystate.c
M Python/pythonrun.c
M Tools/c-analyzer/cpython/globals-to-fix.tsv
M Tools/c-analyzer/cpython/ignored.tsv

diff --git a/Include/cpython/modsupport.h b/Include/cpython/modsupport.h
index d8458923b3fa..88f34fe7513b 100644
--- a/Include/cpython/modsupport.h
+++ b/Include/cpython/modsupport.h
@@ -106,5 +106,3 @@ PyAPI_FUNC(PyObject * const *) _PyArg_UnpackKeywordsWithVararg(
                            (minpos), (maxpos), (minkw), (buf)))
 
 PyAPI_FUNC(PyObject *) _PyModule_CreateInitialized(PyModuleDef*, int apiver);
-
-PyAPI_DATA(const char *) _Py_PackageContext;
diff --git a/Include/internal/pycore_fileutils.h b/Include/internal/pycore_fileutils.h
index 3ce8108e4e04..ac89c43d569c 100644
--- a/Include/internal/pycore_fileutils.h
+++ b/Include/internal/pycore_fileutils.h
@@ -10,6 +10,11 @@ extern "C" {
 
 #include <locale.h>   /* struct lconv */
 
+
+struct _fileutils_state {
+    int force_ascii;
+};
+
 typedef enum {
     _Py_ERROR_UNKNOWN=0,
     _Py_ERROR_STRICT,
diff --git a/Include/internal/pycore_floatobject.h b/Include/internal/pycore_floatobject.h
index 8a655543329f..27c63bc87f3e 100644
--- a/Include/internal/pycore_floatobject.h
+++ b/Include/internal/pycore_floatobject.h
@@ -19,6 +19,18 @@ extern void _PyFloat_FiniType(PyInterpreterState *);
 
 /* other API */
 
+enum _py_float_format_type {
+    _py_float_format_unknown,
+    _py_float_format_ieee_big_endian,
+    _py_float_format_ieee_little_endian,
+};
+
+struct _Py_float_runtime_state {
+    enum _py_float_format_type float_format;
+    enum _py_float_format_type double_format;
+};
+
+
 #ifndef WITH_FREELISTS
 // without freelists
 #  define PyFloat_MAXFREELIST 0
diff --git a/Include/internal/pycore_import.h b/Include/internal/pycore_import.h
index 8ba9666cdcf9..9036dff67253 100644
--- a/Include/internal/pycore_import.h
+++ b/Include/internal/pycore_import.h
@@ -32,6 +32,8 @@ struct _import_runtime_state {
         _PyTime_t accumulated;
         int header;
     } find_and_load;
+    /* Package context -- the full module name for package imports */
+    const char * pkgcontext;
 };
 
 
diff --git a/Include/internal/pycore_interp.h b/Include/internal/pycore_interp.h
index a13bc32e1144..b7fc4b480d7f 100644
--- a/Include/internal/pycore_interp.h
+++ b/Include/internal/pycore_interp.h
@@ -28,6 +28,7 @@ extern "C" {
 
 
 struct _pending_calls {
+    int busy;
     PyThread_type_lock lock;
     /* Request for running pending calls. */
     _Py_atomic_int calls_to_do;
diff --git a/Include/internal/pycore_pyhash.h b/Include/internal/pycore_pyhash.h
index a229f8d8b7f0..34dfa5377128 100644
--- a/Include/internal/pycore_pyhash.h
+++ b/Include/internal/pycore_pyhash.h
@@ -5,6 +5,36 @@
 #  error "this header requires Py_BUILD_CORE define"
 #endif
 
-uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
 
+struct pyhash_runtime_state {
+    struct {
+#ifndef MS_WINDOWS
+        int fd;
+        dev_t st_dev;
+        ino_t st_ino;
+#else
+    // This is a placeholder so the struct isn't empty on Windows.
+    int _not_used;
+#endif
+    } urandom_cache;
+};
+
+#ifndef MS_WINDOWS
+# define _py_urandom_cache_INIT \
+    { \
+        .fd = -1, \
+    }
+#else
+# define _py_urandom_cache_INIT {0}
 #endif
+
+#define pyhash_state_INIT \
+    { \
+        .urandom_cache = _py_urandom_cache_INIT, \
+    }
+
+
+uint64_t _Py_KeyedHash(uint64_t, const char *, Py_ssize_t);
+
+
+#endif  // Py_INTERNAL_HASH_H
diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h
index 359b809d5870..4c0ffa7a9b1a 100644
--- a/Include/internal/pycore_pylifecycle.h
+++ b/Include/internal/pycore_pylifecycle.h
@@ -14,10 +14,6 @@ extern "C" {
 struct _PyArgv;
 struct pyruntimestate;
 
-/* True if the main interpreter thread exited due to an unhandled
- * KeyboardInterrupt exception, suggesting the user pressed ^C. */
-PyAPI_DATA(int) _Py_UnhandledKeyboardInterrupt;
-
 extern int _Py_SetFileSystemEncoding(
     const char *encoding,
     const char *errors);
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index 8b2b9d7a85b2..f8b988021b99 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -10,11 +10,13 @@ extern "C" {
 
 #include "pycore_atomic.h"          /* _Py_atomic_address */
 #include "pycore_dtoa.h"            // struct _dtoa_runtime_state
+#include "pycore_floatobject.h"     // struct _Py_float_runtime_state
 #include "pycore_gil.h"             // struct _gil_runtime_state
 #include "pycore_global_objects.h"  // struct _Py_global_objects
 #include "pycore_import.h"          // struct _import_runtime_state
 #include "pycore_interp.h"          // PyInterpreterState
 #include "pycore_pymem.h"           // struct _pymem_allocators
+#include "pycore_pyhash.h"          // struct pyhash_runtime_state
 #include "pycore_obmalloc.h"        // struct obmalloc_state
 #include "pycore_unicodeobject.h"   // struct _Py_unicode_runtime_ids
 
@@ -92,6 +94,12 @@ typedef struct pyruntimestate {
 
     struct _pymem_allocators allocators;
     struct _obmalloc_state obmalloc;
+    struct pyhash_runtime_state pyhash_state;
+    struct {
+        /* True if the main interpreter thread exited due to an unhandled
+         * KeyboardInterrupt exception, suggesting the user pressed ^C. */
+        int unhandled_keyboard_interrupt;
+    } signals;
 
     struct pyinterpreters {
         PyThread_type_lock mutex;
@@ -131,6 +139,7 @@ typedef struct pyruntimestate {
         struct _PyTraceMalloc_Config config;
     } tracemalloc;
     struct _dtoa_runtime_state dtoa;
+    struct _fileutils_state fileutils;
 
     PyPreConfig preconfig;
 
@@ -140,7 +149,8 @@ typedef struct pyruntimestate {
     void *open_code_userdata;
     _Py_AuditHookEntry *audit_hook_head;
 
-    struct _Py_unicode_runtime_ids unicode_ids;
+    struct _Py_float_runtime_state float_state;
+    struct _Py_unicode_runtime_state unicode_state;
 
     struct {
         /* Used to set PyTypeObject.tp_version_tag */
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index 6bdee36a851c..37bc54ff96c6 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -19,30 +19,18 @@ extern "C" {
 
 #define _PyRuntimeState_INIT(runtime) \
     { \
-        .gilstate = { \
-            .check_enabled = 1, \
-            /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
-               in accordance with the specification. */ \
-            .autoTSSkey = Py_tss_NEEDS_INIT, \
-        }, \
         .allocators = { \
             _pymem_allocators_standard_INIT(runtime), \
             _pymem_allocators_debug_INIT, \
             _pymem_allocators_obj_arena_INIT, \
         }, \
         .obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
+        .pyhash_state = pyhash_state_INIT, \
         .interpreters = { \
             /* This prevents interpreters from getting created \
               until _PyInterpreterState_Enable() is called. */ \
             .next_id = -1, \
         }, \
-        .tracemalloc = { \
-            .config = _PyTraceMalloc_Config_INIT, \
-        }, \
-        .dtoa = _dtoa_runtime_state_INIT(runtime), \
-        .types = { \
-            .next_version_tag = 1, \
-        }, \
         .imports = { \
             .lock = { \
                 .mutex = NULL, \
@@ -53,6 +41,26 @@ extern "C" {
                 .header = 1, \
             }, \
         }, \
+        .gilstate = { \
+            .check_enabled = 1, \
+            /* A TSS key must be initialized with Py_tss_NEEDS_INIT \
+               in accordance with the specification. */ \
+            .autoTSSkey = Py_tss_NEEDS_INIT, \
+        }, \
+        .tracemalloc = { \
+            .config = _PyTraceMalloc_Config_INIT, \
+        }, \
+        .dtoa = _dtoa_runtime_state_INIT(runtime), \
+        .fileutils = { \
+            .force_ascii = -1, \
+        }, \
+        .float_state = { \
+            .float_format = _py_float_format_unknown, \
+            .double_format = _py_float_format_unknown, \
+        }, \
+        .types = { \
+            .next_version_tag = 1, \
+        }, \
         .global_objects = { \
             .singletons = { \
                 .small_ints = _Py_small_ints_INIT, \
diff --git a/Include/internal/pycore_unicodeobject.h b/Include/internal/pycore_unicodeobject.h
index 63bf04b3e1b8..b315ca1ae5b6 100644
--- a/Include/internal/pycore_unicodeobject.h
+++ b/Include/internal/pycore_unicodeobject.h
@@ -31,6 +31,10 @@ struct _Py_unicode_runtime_ids {
     Py_ssize_t next_index;
 };
 
+struct _Py_unicode_runtime_state {
+    struct _Py_unicode_runtime_ids ids;
+};
+
 /* fs_codec.encoding is initialized to NULL.
    Later, it is set to a non-NULL string by _PyUnicode_InitEncodings(). */
 struct _Py_unicode_fs_codec {
diff --git a/Modules/main.c b/Modules/main.c
index aa523fc58d93..7edfeb3365b4 100644
--- a/Modules/main.c
+++ b/Modules/main.c
@@ -296,10 +296,10 @@ pymain_run_module(const wchar_t *modname, int set_argv0)
         Py_DECREF(module);
         return pymain_exit_err_print();
     }
-    _Py_UnhandledKeyboardInterrupt = 0;
+    _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
     result = PyObject_Call(runmodule, runargs, NULL);
     if (!result && PyErr_Occurred() == PyExc_KeyboardInterrupt) {
-        _Py_UnhandledKeyboardInterrupt = 1;
+        _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
     }
     Py_DECREF(runpy);
     Py_DECREF(runmodule);
@@ -696,7 +696,7 @@ Py_RunMain(void)
 
     pymain_free();
 
-    if (_Py_UnhandledKeyboardInterrupt) {
+    if (_PyRuntime.signals.unhandled_keyboard_interrupt) {
         exitcode = exit_sigint();
     }
 
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
index 65383b2802c1..46016e946ad3 100644
--- a/Objects/floatobject.c
+++ b/Objects/floatobject.c
@@ -1723,12 +1723,14 @@ float___getnewargs___impl(PyObject *self)
 }
 
 /* this is for the benefit of the pack/unpack routines below */
+typedef enum _py_float_format_type float_format_type;
+#define unknown_format _py_float_format_unknown
+#define ieee_big_endian_format _py_float_format_ieee_big_endian
+#define ieee_little_endian_format _py_float_format_ieee_little_endian
 
-typedef enum {
-    unknown_format, ieee_big_endian_format, ieee_little_endian_format
-} float_format_type;
+#define float_format (_PyRuntime.float_state.float_format)
+#define double_format (_PyRuntime.float_state.double_format)
 
-static float_format_type double_format, float_format;
 
 /*[clinic input]
 @classmethod
@@ -1929,13 +1931,9 @@ PyTypeObject PyFloat_Type = {
     .tp_vectorcall = (vectorcallfunc)float_vectorcall,
 };
 
-void
-_PyFloat_InitState(PyInterpreterState *interp)
+static void
+_init_global_state(void)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
-        return;
-    }
-
     float_format_type detected_double_format, detected_float_format;
 
     /* We attempt to determine if this machine is using IEEE
@@ -1985,6 +1983,15 @@ _PyFloat_InitState(PyInterpreterState *interp)
     float_format = detected_float_format;
 }
 
+void
+_PyFloat_InitState(PyInterpreterState *interp)
+{
+    if (!_Py_IsMainInterpreter(interp)) {
+        return;
+    }
+    _init_global_state();
+}
+
 PyStatus
 _PyFloat_InitTypes(PyInterpreterState *interp)
 {
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c
index 4a423a719e90..8e03f2446f6f 100644
--- a/Objects/moduleobject.c
+++ b/Objects/moduleobject.c
@@ -218,6 +218,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
        _Py_PackageContext, and PyModule_Create*() will substitute this
        (if the name actually matches).
     */
+#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
     if (_Py_PackageContext != NULL) {
         const char *p = strrchr(_Py_PackageContext, '.');
         if (p != NULL && strcmp(module->m_name, p+1) == 0) {
@@ -225,6 +226,7 @@ _PyModule_CreateInitialized(PyModuleDef* module, int module_api_version)
             _Py_PackageContext = NULL;
         }
     }
+#undef _Py_PackageContext
     if ((m = (PyModuleObject*)PyModule_New(name)) == NULL)
         return NULL;
 
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index eaa8f581a75a..b1acfc71379c 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -1856,7 +1856,7 @@ _PyUnicode_FromId(_Py_Identifier *id)
 
     Py_ssize_t index = _Py_atomic_size_get(&id->index);
     if (index < 0) {
-        struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_ids;
+        struct _Py_unicode_runtime_ids *rt_ids = &interp->runtime->unicode_state.ids;
 
         PyThread_acquire_lock(rt_ids->lock, WAIT_LOCK);
         // Check again to detect concurrent access. Another thread can have
@@ -14491,12 +14491,14 @@ PyTypeObject PyUnicode_Type = {
 
 /* Initialize the Unicode implementation */
 
-void
-_PyUnicode_InitState(PyInterpreterState *interp)
+static void
+_init_global_state(void)
 {
-    if (!_Py_IsMainInterpreter(interp)) {
+    static int initialized = 0;
+    if (initialized) {
         return;
     }
+    initialized = 1;
 
     /* initialize the linebreak bloom filter */
     const Py_UCS2 linebreak[] = {
@@ -14514,6 +14516,15 @@ _PyUnicode_InitState(PyInterpreterState *interp)
         Py_ARRAY_LENGTH(linebreak));
 }
 
+void
+_PyUnicode_InitState(PyInterpreterState *interp)
+{
+    if (!_Py_IsMainInterpreter(interp)) {
+        return;
+    }
+    _init_global_state();
+}
+
 
 PyStatus
 _PyUnicode_InitGlobalObjects(PyInterpreterState *interp)
diff --git a/Python/bootstrap_hash.c b/Python/bootstrap_hash.c
index 3a2a7318086f..587063ef1ab2 100644
--- a/Python/bootstrap_hash.c
+++ b/Python/bootstrap_hash.c
@@ -1,6 +1,7 @@
 #include "Python.h"
 #include "pycore_initconfig.h"
 #include "pycore_fileutils.h"     // _Py_fstat_noraise()
+#include "pycore_runtime.h"       // _PyRuntime
 
 #ifdef MS_WINDOWS
 #  include <windows.h>
@@ -263,11 +264,7 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise)
 #endif /* defined(HAVE_GETENTROPY) && !(defined(__sun) && defined(__SVR4)) */
 
 
-static struct {
-    int fd;
-    dev_t st_dev;
-    ino_t st_ino;
-} urandom_cache = { -1 };
+#define urandom_cache (_PyRuntime.pyhash_state.urandom_cache)
 
 /* Read random bytes from the /dev/urandom device:
 
@@ -402,6 +399,9 @@ dev_urandom_close(void)
         urandom_cache.fd = -1;
     }
 }
+
+#undef urandom_cache
+
 #endif /* !MS_WINDOWS */
 
 
diff --git a/Python/ceval_gil.c b/Python/ceval_gil.c
index 9b9d7dc1d1af..83f4e91e5457 100644
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -819,11 +819,10 @@ make_pending_calls(PyInterpreterState *interp)
     }
 
     /* don't perform recursive pending calls */
-    static int busy = 0;
-    if (busy) {
+    if (interp->ceval.pending.busy) {
         return 0;
     }
-    busy = 1;
+    interp->ceval.pending.busy = 1;
 
     /* unsignal before starting to call callbacks, so that any callback
        added in-between re-signals */
@@ -851,11 +850,11 @@ make_pending_calls(PyInterpreterState *interp)
         }
     }
 
-    busy = 0;
+    interp->ceval.pending.busy = 0;
     return res;
 
 error:
-    busy = 0;
+    interp->ceval.pending.busy = 0;
     SIGNAL_PENDING_CALLS(interp);
     return res;
 }
diff --git a/Python/fileutils.c b/Python/fileutils.c
index fb1e5ef9a030..244bd899b3bd 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -191,7 +191,7 @@ extern int _Py_normalize_encoding(const char *, char *, size_t);
           Py_DecodeLocale() uses mbstowcs()
       -1: unknown, need to call check_force_ascii() to get the value
 */
-static int force_ascii = -1;
+#define force_ascii (_PyRuntime.fileutils.force_ascii)
 
 static int
 check_force_ascii(void)
diff --git a/Python/importdl.c b/Python/importdl.c
index 870ae2730071..40227674ca47 100644
--- a/Python/importdl.c
+++ b/Python/importdl.c
@@ -160,6 +160,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
     p0 = (PyModInitFunction)exportfunc;
 
     /* Package context is needed for single-phase init */
+#define _Py_PackageContext (_PyRuntime.imports.pkgcontext)
     oldcontext = _Py_PackageContext;
     _Py_PackageContext = PyUnicode_AsUTF8(name_unicode);
     if (_Py_PackageContext == NULL) {
@@ -168,6 +169,7 @@ _PyImport_LoadDynamicModuleWithSpec(PyObject *spec, FILE *fp)
     }
     m = _PyImport_InitFunc_TrampolineCall(p0);
     _Py_PackageContext = oldcontext;
+#undef _Py_PackageContext
 
     if (m == NULL) {
         if (!PyErr_Occurred()) {
diff --git a/Python/modsupport.c b/Python/modsupport.c
index ee4bf14e63e1..b9a10dc157e7 100644
--- a/Python/modsupport.c
+++ b/Python/modsupport.c
@@ -10,9 +10,6 @@ typedef double va_double;
 static PyObject *va_build_value(const char *, va_list, int);
 static PyObject **va_build_stack(PyObject **small_stack, Py_ssize_t small_stack_len, const char *, va_list, int, Py_ssize_t*);
 
-/* Package context -- the full module name for package imports */
-const char *_Py_PackageContext = NULL;
-
 
 int
 _Py_convert_optional_to_ssize_t(PyObject *obj, void *result)
diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c
index 7ca284ef1efb..10636b4d15d7 100644
--- a/Python/pylifecycle.c
+++ b/Python/pylifecycle.c
@@ -77,8 +77,6 @@ static PyStatus init_sys_streams(PyThreadState *tstate);
 static void wait_for_thread_shutdown(PyThreadState *tstate);
 static void call_ll_exitfuncs(_PyRuntimeState *runtime);
 
-int _Py_UnhandledKeyboardInterrupt = 0;
-
 /* The following places the `_PyRuntime` structure in a location that can be
  * found without any external information. This is meant to ease access to the
  * interpreter state for various runtime debugging tools, but is *not* an
diff --git a/Python/pystate.c b/Python/pystate.c
index 5c9e4ff85536..b94fbf6ca0ba 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -137,8 +137,8 @@ init_runtime(_PyRuntimeState *runtime,
     // Set it to the ID of the main thread of the main interpreter.
     runtime->main_thread = PyThread_get_thread_ident();
 
-    runtime->unicode_ids.next_index = unicode_next_index;
-    runtime->unicode_ids.lock = unicode_ids_mutex;
+    runtime->unicode_state.ids.next_index = unicode_next_index;
+    runtime->unicode_state.ids.lock = unicode_ids_mutex;
 
     runtime->_initialized = 1;
 }
@@ -154,7 +154,7 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
     _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;
+    Py_ssize_t unicode_next_index = runtime->unicode_state.ids.next_index;
 
     PyThread_type_lock lock1, lock2, lock3, lock4;
     if (alloc_for_runtime(&lock1, &lock2, &lock3, &lock4) != 0) {
@@ -186,7 +186,7 @@ _PyRuntimeState_Fini(_PyRuntimeState *runtime)
 
     FREE_LOCK(runtime->interpreters.mutex);
     FREE_LOCK(runtime->xidregistry.mutex);
-    FREE_LOCK(runtime->unicode_ids.lock);
+    FREE_LOCK(runtime->unicode_state.ids.lock);
     FREE_LOCK(runtime->getargs.mutex);
 
 #undef FREE_LOCK
@@ -209,7 +209,7 @@ _PyRuntimeState_ReInitThreads(_PyRuntimeState *runtime)
 
     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);
+    int reinit_unicode_ids = _PyThread_at_fork_reinit(&runtime->unicode_state.ids.lock);
     int reinit_getargs = _PyThread_at_fork_reinit(&runtime->getargs.mutex);
 
     PyMem_SetAllocator(PYMEM_DOMAIN_RAW, &old_alloc);
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 1c7ac4af63c6..eead707b5410 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1688,7 +1688,8 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py
      * uncaught exception to trigger an unexplained signal exit from a future
      * Py_Main() based one.
      */
-    _Py_UnhandledKeyboardInterrupt = 0;
+    // XXX Isn't this dealt with by the move to _PyRuntimeState?
+    _PyRuntime.signals.unhandled_keyboard_interrupt = 0;
 
     /* Set globals['__builtins__'] if it doesn't exist */
     if (globals != NULL && _PyDict_GetItemStringWithError(globals, "__builtins__") == NULL) {
@@ -1702,7 +1703,7 @@ run_eval_code_obj(PyThreadState *tstate, PyCodeObject *co, PyObject *globals, Py
 
     v = PyEval_EvalCode((PyObject*)co, globals, locals);
     if (!v && _PyErr_Occurred(tstate) == PyExc_KeyboardInterrupt) {
-        _Py_UnhandledKeyboardInterrupt = 1;
+        _PyRuntime.signals.unhandled_keyboard_interrupt = 1;
     }
     return v;
 }
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index b4ac9120d98b..ee0c85bd425e 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -336,17 +336,7 @@ Python/perf_trampoline.c	-	perf_status	-
 Python/perf_trampoline.c	-	extra_code_index	-
 Python/perf_trampoline.c	-	code_arena	-
 Python/perf_trampoline.c	-	trampoline_api	-
-Parser/pegen.c	-	memo_statistics	-
-Python/bootstrap_hash.c	-	urandom_cache	-
-Python/ceval_gil.c	make_pending_calls	busy	-
-Python/ceval.c	_PyEval_SetProfile	reentrant	-
-Python/ceval.c	_PyEval_SetTrace	reentrant	-
-Python/modsupport.c	-	_Py_PackageContext	-
 Python/thread_pthread_stubs.h	-	py_tls_entries	-
-Python/pyfpe.c	-	PyFPE_counter	-
-Python/pylifecycle.c	_Py_FatalErrorFormat	reentrant	-
-Python/pylifecycle.c	-	_Py_UnhandledKeyboardInterrupt	-
-Python/pylifecycle.c	fatal_error	reentrant	-
 
 
 ##################################
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 0a6f3ec8152d..242deace8c94 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -1,16 +1,95 @@
 filename	funcname	name	reason
 #???	-	somevar	???
 
+# All globals here are technically mutable but known to be safe.
+
+
+##################################
+# process-global resources
+
+# Initialization for these should be idempotent.
+
+#-----------------------
+# effectively const, set once before/during first init
+
+Modules/getbuildinfo.c	-	buildinfo	-
+Modules/getbuildinfo.c	-	initialized	-
+Python/getversion.c	-	initialized	-
+Python/getversion.c	-	version	-
+
+#-----------------------
+# effectively const, set once during first init
+
+Python/bootstrap_hash.c	-	_Py_HashSecret_Initialized	-
+Python/pyhash.c	-	_Py_HashSecret	-
+Python/thread.c	-	initialized	-
+Python/thread_pthread.h	-	condattr_monotonic	-
+
+# safe static buffer used during one-time initialization
+Python/thread_pthread.h	init_condattr	ca	-
+
+# indicators for process-global resource availability/capability
+Python/bootstrap_hash.c	py_getrandom	getrandom_works	-
+Python/fileutils.c	-	_Py_open_cloexec_works	-
+Python/fileutils.c	set_inheritable	ioctl_works	-
+
+#-----------------------
+# effectively const but set once lazily (*after* first init)
+
+Objects/longobject.c	long_from_non_binary_base	log_base_BASE	-
+Objects/longobject.c	long_from_non_binary_base	convwidth_base	-
+Objects/longobject.c	long_from_non_binary_base	convmultmax_base	-
+Objects/unicodeobject.c	-	bloom_linebreak	-
+Objects/unicodeobject.c	_init_global_state	initialized	-
+
+# XXX Move to _PyRuntimeState?
+Parser/action_helpers.c	_PyPegen_dummy_name	cache	-
+
+
 ##################################
-# mutable but known to be safe
+# state tied to C main() (only in main thread)
+
+#-----------------------
+# handling C argv
+
+Python/getopt.c	-	_PyOS_optarg	-
+Python/getopt.c	-	_PyOS_opterr	-
+Python/getopt.c	-	_PyOS_optind	-
+Python/getopt.c	-	opt_ptr	-
+Python/pathconfig.c	-	_Py_path_config	-
+
+#-----------------------
+# REPL
+
+Parser/myreadline.c	-	_PyOS_ReadlineLock	-
+Parser/myreadline.c	-	_PyOS_ReadlineTState	-
+Parser/myreadline.c	-	PyOS_InputHook	-
+Parser/myreadline.c	-	PyOS_ReadlineFunctionPointer	-
+
+
+##################################
+# state tied to each runtime init/fini cycle
 
 Python/pylifecycle.c	-	_PyRuntime	-
+Python/pylifecycle.c	-	runtime_initialized	-
 
 # All uses of _PyArg_Parser are handled in c-analyzr/cpython/_analyzer.py.
 
 #-----------------------
-# legacy config flags
+# effectively const once init finishes
+
+# set by embedders before init (whether directly or through a call)
+Python/initconfig.c	-	_Py_StandardStreamEncoding	-
+Python/initconfig.c	-	_Py_StandardStreamErrors	-
+Python/initconfig.c	-	orig_argv	-
+
+# deprecated
+Python/preconfig.c	-	Py_FileSystemDefaultEncoding	-
+Python/preconfig.c	-	Py_HasFileSystemDefaultEncoding	-
+Python/preconfig.c	-	Py_FileSystemDefaultEncodeErrors	-
+Python/preconfig.c	-	_Py_HasFileSystemDefaultEncodeErrors	-
 
+# legacy config flags
 Python/initconfig.c	-	Py_UTF8Mode	-
 Python/initconfig.c	-	Py_DebugFlag	-
 Python/initconfig.c	-	Py_VerboseFlag	-
@@ -30,75 +109,34 @@ Python/initconfig.c	-	Py_IsolatedFlag	-
 Python/initconfig.c	-	Py_LegacyWindowsFSEncodingFlag	-
 Python/initconfig.c	-	Py_LegacyWindowsStdioFlag	-
 
-#-----------------------
-# effectively const, initialized before init
-
+# initialized statically, customized by embedders
 Python/frozen.c	-	PyImport_FrozenModules	-
 Python/import.c	-	inittab_copy	-
 Python/import.c	-	PyImport_Inittab	-
 
-#-----------------------
-# effectively const, initialized before/during init
+# used temporarily during init
+Python/sysmodule.c	-	_preinit_warnoptions	-
+Python/sysmodule.c	-	_preinit_xoptions	-
 
-Modules/getbuildinfo.c	-	buildinfo	-
-Modules/getbuildinfo.c	-	initialized	-
-Python/getversion.c	-	initialized	-
-Python/getversion.c	-	version	-
 
-#-----------------------
-# effectively const, initialized during init
+##################################
+# special-use diagnistic state
 
-Objects/floatobject.c	-	double_format	-
-Objects/floatobject.c	-	float_format	-
-Objects/unicodeobject.c	-	bloom_linebreak	-
-Python/bootstrap_hash.c	py_getrandom	getrandom_works	-
-Python/bootstrap_hash.c	-	_Py_HashSecret_Initialized	-
-Python/fileutils.c	-	_Py_open_cloexec_works	-
-Python/fileutils.c	-	force_ascii	-
-Python/fileutils.c	set_inheritable	ioctl_works	-
-Python/import.c	import_find_and_load	header	-
-Python/initconfig.c	-	orig_argv	-
-Python/preconfig.c	-	Py_FileSystemDefaultEncoding	-
-Python/preconfig.c	-	Py_HasFileSystemDefaultEncoding	-
-Python/preconfig.c	-	Py_FileSystemDefaultEncodeErrors	-
-Python/preconfig.c	-	_Py_HasFileSystemDefaultEncodeErrors	-
-Python/pyhash.c	-	_Py_HashSecret	-
-Python/pylifecycle.c	-	runtime_initialized	-
-Python/sysmodule.c	-	_preinit_warnoptions	-
-Python/sysmodule.c	-	_preinit_xoptions	-
-Python/thread.c	-	initialized	-
-Python/thread_pthread.h	-	condattr_monotonic	-
-Python/thread_pthread.h	init_condattr	ca	-
+Parser/pegen.c	-	memo_statistics	-
 
-# set by embedders during init
-Python/initconfig.c	-	_Py_StandardStreamEncoding	-
-Python/initconfig.c	-	_Py_StandardStreamErrors	-
 
-#-----------------------
-# effectively const but initialized lazily
-# XXX Move them to _PyRuntimeState?
+##################################
+# one-off temporary state
 
-# idempotent
-Objects/longobject.c	long_from_non_binary_base	log_base_BASE	-
-Objects/longobject.c	long_from_non_binary_base	convwidth_base	-
-Objects/longobject.c	long_from_non_binary_base	convmultmax_base	-
-Parser/action_helpers.c	_PyPegen_dummy_name	cache	-
+# This is safe enough.
+Python/pylifecycle.c	_Py_FatalErrorFormat	reentrant	-
+Python/pylifecycle.c	fatal_error	reentrant	-
 
-#-----------------------
-# used only in the main thread
 
-# REPL
-Parser/myreadline.c	-	_PyOS_ReadlineLock	-
-Parser/myreadline.c	-	_PyOS_ReadlineTState	-
-Parser/myreadline.c	-	PyOS_InputHook	-
-Parser/myreadline.c	-	PyOS_ReadlineFunctionPointer	-
+##################################
+# not used (kept for compatibility)
 
-# handling C argv
-Python/getopt.c	-	_PyOS_optarg	-
-Python/getopt.c	-	_PyOS_opterr	-
-Python/getopt.c	-	_PyOS_optind	-
-Python/getopt.c	-	opt_ptr	-
-Python/pathconfig.c	-	_Py_path_config	-
+Python/pyfpe.c	-	PyFPE_counter	-
 
 
 ##################################



More information about the Python-checkins mailing list