]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-81057: Move OS-Related Globals to _PyRuntimeState (gh-100082)
authorEric Snow <ericsnowcurrently@gmail.com>
Thu, 8 Dec 2022 22:38:06 +0000 (15:38 -0700)
committerGitHub <noreply@github.com>
Thu, 8 Dec 2022 22:38:06 +0000 (15:38 -0700)
https://github.com/python/cpython/issues/81057

14 files changed:
Include/internal/pycore_global_objects_fini_generated.h
Include/internal/pycore_global_strings.h
Include/internal/pycore_os.h [new file with mode: 0644]
Include/internal/pycore_runtime.h
Include/internal/pycore_runtime_init.h
Include/internal/pycore_runtime_init_generated.h
Include/internal/pycore_unicodeobject_generated.h
Lib/test/test_os.py
Makefile.pre.in
Modules/posixmodule.c
PCbuild/pythoncore.vcxproj
PCbuild/pythoncore.vcxproj.filters
Tools/c-analyzer/cpython/globals-to-fix.tsv
Tools/c-analyzer/cpython/ignored.tsv

index 9951fa9951e67adc07076d67111b9cb025335bf5..6aba2f19ebde4a94fb4a8e1240a7fc0394c3b767 100644 (file)
@@ -1051,6 +1051,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(node_offset));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(ns));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nstype));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(nt));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(null));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(number));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(obj));
@@ -1089,6 +1090,7 @@ _PyStaticObjects_CheckRefcnt(PyInterpreterState *interp) {
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos1));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(pos2));
+    _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(posix));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(print_file_and_line));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(priority));
     _PyStaticObject_CheckRefcnt((PyObject *)&_Py_ID(progress));
index 12144b02f45574b291cdb7dc4c02b2a6f1c94f8d..acb9a4fbb92dce04a0bdb3ef7c11c5355711d430 100644 (file)
@@ -537,6 +537,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(node_offset)
         STRUCT_FOR_ID(ns)
         STRUCT_FOR_ID(nstype)
+        STRUCT_FOR_ID(nt)
         STRUCT_FOR_ID(null)
         STRUCT_FOR_ID(number)
         STRUCT_FOR_ID(obj)
@@ -575,6 +576,7 @@ struct _Py_global_strings {
         STRUCT_FOR_ID(pos)
         STRUCT_FOR_ID(pos1)
         STRUCT_FOR_ID(pos2)
+        STRUCT_FOR_ID(posix)
         STRUCT_FOR_ID(print_file_and_line)
         STRUCT_FOR_ID(priority)
         STRUCT_FOR_ID(progress)
diff --git a/Include/internal/pycore_os.h b/Include/internal/pycore_os.h
new file mode 100644 (file)
index 0000000..e4899bd
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef Py_INTERNAL_OS_H
+#define Py_INTERNAL_OS_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef Py_BUILD_CORE
+#  error "this header requires Py_BUILD_CORE define"
+#endif
+
+
+#ifndef MS_WINDOWS
+#define _OS_NEED_TICKS_PER_SECOND
+# define need_ticks_per_second_STATE \
+    long ticks_per_second;
+# define need_ticks_per_second_INIT \
+    .ticks_per_second = -1,
+#else
+# define need_ticks_per_second_STATE
+# define need_ticks_per_second_INIT
+#endif /* MS_WINDOWS */
+
+
+struct _os_runtime_state {
+    int _not_used;
+    need_ticks_per_second_STATE
+};
+# define _OS_RUNTIME_INIT \
+    { \
+        ._not_used = 0, \
+        need_ticks_per_second_INIT \
+    }
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_INTERNAL_OS_H */
index 0720e2ed4422df786f94a8a1b69e2577e1f791ec..c6b48cae7760fc38c20d57b430c940c96fe44528 100644 (file)
@@ -21,6 +21,7 @@ extern "C" {
 #include "pycore_pymem.h"           // struct _pymem_allocators
 #include "pycore_pyhash.h"          // struct pyhash_runtime_state
 #include "pycore_obmalloc.h"        // struct obmalloc_state
+#include "pycore_os.h"              // struct _os_runtime_state
 #include "pycore_unicodeobject.h"   // struct _Py_unicode_runtime_ids
 
 struct _getargs_runtime_state {
@@ -103,6 +104,7 @@ typedef struct pyruntimestate {
          * KeyboardInterrupt exception, suggesting the user pressed ^C. */
         int unhandled_keyboard_interrupt;
     } signals;
+    struct _os_runtime_state os;
 
     struct pyinterpreters {
         PyThread_type_lock mutex;
index ab53876e355fd8d2c606875f67b7921ef48ca92f..70263892e570b23c703e4009e87b051575c50acd 100644 (file)
@@ -26,6 +26,7 @@ extern "C" {
         }, \
         .obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
         .pyhash_state = pyhash_state_INIT, \
+        .os = _OS_RUNTIME_INIT, \
         .interpreters = { \
             /* This prevents interpreters from getting created \
               until _PyInterpreterState_Enable() is called. */ \
index 87b0f2ed8dfa8c6f5f4bc775bca6a18bcd07b5a9..6d1b8702c7769887aa986b8cf0555292d640bbdf 100644 (file)
@@ -1043,6 +1043,7 @@ extern "C" {
     INIT_ID(node_offset), \
     INIT_ID(ns), \
     INIT_ID(nstype), \
+    INIT_ID(nt), \
     INIT_ID(null), \
     INIT_ID(number), \
     INIT_ID(obj), \
@@ -1081,6 +1082,7 @@ extern "C" {
     INIT_ID(pos), \
     INIT_ID(pos1), \
     INIT_ID(pos2), \
+    INIT_ID(posix), \
     INIT_ID(print_file_and_line), \
     INIT_ID(priority), \
     INIT_ID(progress), \
index 80be342b5b3b44fa6e802183e4aeb0f410c7a0f7..7f407c0141b8a5ebfbb6d4bc51d636d03d133048 100644 (file)
@@ -980,6 +980,8 @@ _PyUnicode_InitStaticStrings(void) {
     PyUnicode_InternInPlace(&string);
     string = &_Py_ID(nstype);
     PyUnicode_InternInPlace(&string);
+    string = &_Py_ID(nt);
+    PyUnicode_InternInPlace(&string);
     string = &_Py_ID(null);
     PyUnicode_InternInPlace(&string);
     string = &_Py_ID(number);
@@ -1056,6 +1058,8 @@ _PyUnicode_InitStaticStrings(void) {
     PyUnicode_InternInPlace(&string);
     string = &_Py_ID(pos2);
     PyUnicode_InternInPlace(&string);
+    string = &_Py_ID(posix);
+    PyUnicode_InternInPlace(&string);
     string = &_Py_ID(print_file_and_line);
     PyUnicode_InternInPlace(&string);
     string = &_Py_ID(priority);
index 94db8bb7737acdd0bd143f85d52cb12592c8326a..e0577916428a08dc9fa5ea2cee9821edad8c0e30 100644 (file)
@@ -606,12 +606,13 @@ class StatAttributeTests(unittest.TestCase):
     def test_stat_result_pickle(self):
         result = os.stat(self.fname)
         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
-            p = pickle.dumps(result, proto)
-            self.assertIn(b'stat_result', p)
-            if proto < 4:
-                self.assertIn(b'cos\nstat_result\n', p)
-            unpickled = pickle.loads(p)
-            self.assertEqual(result, unpickled)
+            with self.subTest(f'protocol {proto}'):
+                p = pickle.dumps(result, proto)
+                self.assertIn(b'stat_result', p)
+                if proto < 4:
+                    self.assertIn(b'cos\nstat_result\n', p)
+                unpickled = pickle.loads(p)
+                self.assertEqual(result, unpickled)
 
     @unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
     def test_statvfs_attributes(self):
index f6df7a620deaed3cbe2f5b91369fc826a91ca2e9..80144e5288755ca2d945ba1486f565401dd24ac1 100644 (file)
@@ -1654,6 +1654,7 @@ PYTHON_HEADERS= \
                $(srcdir)/Include/internal/pycore_object.h \
                $(srcdir)/Include/internal/pycore_obmalloc.h \
                $(srcdir)/Include/internal/pycore_obmalloc_init.h \
+               $(srcdir)/Include/internal/pycore_os.h \
                $(srcdir)/Include/internal/pycore_pathconfig.h \
                $(srcdir)/Include/internal/pycore_pyarena.h \
                $(srcdir)/Include/internal/pycore_pyerrors.h \
index 7fc8aef9b303fc872560aacfccd0ae4ba238a7e1..cbf4d5b3fcec5eb6918c4ba58248bc7393890598 100644 (file)
@@ -495,9 +495,11 @@ extern char        *ctermid_r(char *);
 #ifdef MS_WINDOWS
 #  define INITFUNC PyInit_nt
 #  define MODNAME "nt"
+#  define MODNAME_OBJ &_Py_ID(nt)
 #else
 #  define INITFUNC PyInit_posix
 #  define MODNAME "posix"
+#  define MODNAME_OBJ &_Py_ID(posix)
 #endif
 
 #if defined(__sun)
@@ -974,6 +976,7 @@ typedef struct {
 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
     PyObject *SchedParamType;
 #endif
+    newfunc statresult_new_orig;
     PyObject *StatResultType;
     PyObject *StatVFSResultType;
     PyObject *TerminalSizeType;
@@ -2225,7 +2228,6 @@ static PyStructSequence_Desc waitid_result_desc = {
     5
 };
 #endif
-static newfunc structseq_new;
 
 static PyObject *
 statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -2233,6 +2235,18 @@ statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
     PyStructSequence *result;
     int i;
 
+    // ht_module doesn't get set in PyStructSequence_NewType(),
+    // so we can't use PyType_GetModule().
+    PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
+    if (mod == NULL) {
+        return NULL;
+    }
+    _posixstate *state = get_posix_state(mod);
+    if (state == NULL) {
+        return NULL;
+    }
+#define structseq_new state->statresult_new_orig
+
     result = (PyStructSequence*)structseq_new(type, args, kwds);
     if (!result)
         return NULL;
@@ -9051,10 +9065,23 @@ build_times_result(PyObject *module, double user, double system,
 }
 
 
-#ifndef MS_WINDOWS
-#define NEED_TICKS_PER_SECOND
-static long ticks_per_second = -1;
-#endif /* MS_WINDOWS */
+#ifdef _OS_NEED_TICKS_PER_SECOND
+#define ticks_per_second _PyRuntime.os.ticks_per_second
+static void
+ticks_per_second_init(void)
+{
+    if (ticks_per_second != -1) {
+        return;
+    }
+#  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
+    ticks_per_second = sysconf(_SC_CLK_TCK);
+#  elif defined(HZ)
+    ticks_per_second = HZ;
+#  else
+    ticks_per_second = 60; /* magic fallback value; may be bogus */
+#  endif
+}
+#endif
 
 /*[clinic input]
 os.times
@@ -9089,10 +9116,10 @@ os_times_impl(PyObject *module)
         (double)0,
         (double)0);
 }
+#elif !defined(_OS_NEED_TICKS_PER_SECOND)
+# error "missing ticks_per_second"
 #else /* MS_WINDOWS */
 {
-
-
     struct tms t;
     clock_t c;
     errno = 0;
@@ -15912,7 +15939,7 @@ posixmodule_exec(PyObject *m)
     }
     PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType));
     state->StatResultType = StatResultType;
-    structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
+    state->statresult_new_orig = ((PyTypeObject *)StatResultType)->tp_new;
     ((PyTypeObject *)StatResultType)->tp_new = statresult_new;
 
     statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
@@ -15922,14 +15949,9 @@ posixmodule_exec(PyObject *m)
     }
     PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType));
     state->StatVFSResultType = StatVFSResultType;
-#ifdef NEED_TICKS_PER_SECOND
-#  if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
-    ticks_per_second = sysconf(_SC_CLK_TCK);
-#  elif defined(HZ)
-    ticks_per_second = HZ;
-#  else
-    ticks_per_second = 60; /* magic fallback value; may be bogus */
-#  endif
+
+#ifdef _OS_NEED_TICKS_PER_SECOND
+    ticks_per_second_init();
 #endif
 
 #if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
index f62434370cfdf7294141fa2d8f2af534a153c6f8..fa3924968a6b26dbbacfd58eccc9ac385cb2b3c9 100644 (file)
     <ClInclude Include="..\Include\internal\pycore_object.h" />
     <ClInclude Include="..\Include\internal\pycore_obmalloc.h" />
     <ClInclude Include="..\Include\internal\pycore_obmalloc_init.h" />
+    <ClInclude Include="..\Include\internal\pycore_os.h" />
     <ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
     <ClInclude Include="..\Include\internal\pycore_pyarena.h" />
     <ClInclude Include="..\Include\internal\pycore_pyerrors.h" />
index f44a1ad8550a382da7e748b1e4dcbbc385addfb1..e29c6b2330d176a93d1067df2e28797ca1ba5c5d 100644 (file)
     <ClInclude Include="..\Include\internal\pycore_obmalloc_init.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
+    <ClInclude Include="..\Include\internal\pycore_os.h">
+      <Filter>Include\internal</Filter>
+    </ClInclude>
     <ClInclude Include="..\Include\internal\pycore_pathconfig.h">
       <Filter>Include\internal</Filter>
     </ClInclude>
index 5c8164517f138a6e0f5b4c225dd9df2413fb50ee..8e05bc3e4f23e55eae31f6c2def8c2375686fe99 100644 (file)
@@ -390,9 +390,6 @@ Modules/faulthandler.c      -       old_stack       -
 ##-----------------------
 ## initialized once
 
-Modules/posixmodule.c  os_dup2_impl    dup3_works      -
-Modules/posixmodule.c  -       structseq_new   -
-Modules/posixmodule.c  -       ticks_per_second        -
 Modules/timemodule.c   _PyTime_GetClockWithInfo        initialized     -
 Modules/timemodule.c   _PyTime_GetProcessTimeWithInfo  ticks_per_second        -
 
index 257823574fa8b37ba6ebd4e68a1d1b700fdafaa6..814c55b75c090df50bfc9e134f9f250c798aa7c1 100644 (file)
@@ -11,14 +11,18 @@ filename    funcname        name    reason
 # These are effectively const.
 
 ##-----------------------
-## process-global resources - set during first init
+## process-global resources
 
 ## indicators for resource availability/capability
+# (set during first init)
 Python/bootstrap_hash.c        py_getrandom    getrandom_works -
 Python/fileutils.c     -       _Py_open_cloexec_works  -
 Python/fileutils.c     set_inheritable ioctl_works     -
+# (set lazily, *after* first init)
+# XXX Is this thread-safe?
+Modules/posixmodule.c  os_dup2_impl    dup3_works      -
 
-## resource init
+## resource init - set during first init
 Python/thread.c        -       initialized     -
 Python/thread_pthread.h        -       condattr_monotonic      -
 # safe static buffer used during one-time initialization