[Python-checkins] gh-81057: Move OS-Related Globals to _PyRuntimeState (gh-100082)

ericsnowcurrently webhook-mailer at python.org
Thu Dec 8 17:38:12 EST 2022


https://github.com/python/cpython/commit/cda9f0236fd7800c6db5eec207668c4bfec4a45d
commit: cda9f0236fd7800c6db5eec207668c4bfec4a45d
branch: main
author: Eric Snow <ericsnowcurrently at gmail.com>
committer: ericsnowcurrently <ericsnowcurrently at gmail.com>
date: 2022-12-08T15:38:06-07:00
summary:

gh-81057: Move OS-Related Globals to _PyRuntimeState (gh-100082)

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

files:
A Include/internal/pycore_os.h
M Include/internal/pycore_global_objects_fini_generated.h
M Include/internal/pycore_global_strings.h
M Include/internal/pycore_runtime.h
M Include/internal/pycore_runtime_init.h
M Include/internal/pycore_runtime_init_generated.h
M Include/internal/pycore_unicodeobject_generated.h
M Lib/test/test_os.py
M Makefile.pre.in
M Modules/posixmodule.c
M PCbuild/pythoncore.vcxproj
M PCbuild/pythoncore.vcxproj.filters
M Tools/c-analyzer/cpython/globals-to-fix.tsv
M Tools/c-analyzer/cpython/ignored.tsv

diff --git a/Include/internal/pycore_global_objects_fini_generated.h b/Include/internal/pycore_global_objects_fini_generated.h
index 9951fa9951e6..6aba2f19ebde 100644
--- a/Include/internal/pycore_global_objects_fini_generated.h
+++ b/Include/internal/pycore_global_objects_fini_generated.h
@@ -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));
diff --git a/Include/internal/pycore_global_strings.h b/Include/internal/pycore_global_strings.h
index 12144b02f455..acb9a4fbb92d 100644
--- a/Include/internal/pycore_global_strings.h
+++ b/Include/internal/pycore_global_strings.h
@@ -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
index 000000000000..e4899bd5032d
--- /dev/null
+++ b/Include/internal/pycore_os.h
@@ -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 */
diff --git a/Include/internal/pycore_runtime.h b/Include/internal/pycore_runtime.h
index 0720e2ed4422..c6b48cae7760 100644
--- a/Include/internal/pycore_runtime.h
+++ b/Include/internal/pycore_runtime.h
@@ -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;
diff --git a/Include/internal/pycore_runtime_init.h b/Include/internal/pycore_runtime_init.h
index ab53876e355f..70263892e570 100644
--- a/Include/internal/pycore_runtime_init.h
+++ b/Include/internal/pycore_runtime_init.h
@@ -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. */ \
diff --git a/Include/internal/pycore_runtime_init_generated.h b/Include/internal/pycore_runtime_init_generated.h
index 87b0f2ed8dfa..6d1b8702c776 100644
--- a/Include/internal/pycore_runtime_init_generated.h
+++ b/Include/internal/pycore_runtime_init_generated.h
@@ -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), \
diff --git a/Include/internal/pycore_unicodeobject_generated.h b/Include/internal/pycore_unicodeobject_generated.h
index 80be342b5b3b..7f407c0141b8 100644
--- a/Include/internal/pycore_unicodeobject_generated.h
+++ b/Include/internal/pycore_unicodeobject_generated.h
@@ -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);
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index 94db8bb7737a..e0577916428a 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -606,12 +606,13 @@ def test_stat_attributes_bytes(self):
     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):
diff --git a/Makefile.pre.in b/Makefile.pre.in
index f6df7a620dea..80144e528875 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -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 \
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 7fc8aef9b303..cbf4d5b3fcec 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -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)
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index f62434370cfd..fa3924968a6b 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -236,6 +236,7 @@
     <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" />
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index f44a1ad8550a..e29c6b2330d1 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -612,6 +612,9 @@
     <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>
diff --git a/Tools/c-analyzer/cpython/globals-to-fix.tsv b/Tools/c-analyzer/cpython/globals-to-fix.tsv
index 5c8164517f13..8e05bc3e4f23 100644
--- a/Tools/c-analyzer/cpython/globals-to-fix.tsv
+++ b/Tools/c-analyzer/cpython/globals-to-fix.tsv
@@ -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	-
 
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 257823574fa8..814c55b75c09 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -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



More information about the Python-checkins mailing list