Skip to content

Commit cda9f02

Browse files
gh-81057: Move OS-Related Globals to _PyRuntimeState (gh-100082)
#81057
1 parent c85be73 commit cda9f02

14 files changed

+107
-27
lines changed

Include/internal/pycore_global_objects_fini_generated.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_global_strings.h

+2
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ struct _Py_global_strings {
537537
STRUCT_FOR_ID(node_offset)
538538
STRUCT_FOR_ID(ns)
539539
STRUCT_FOR_ID(nstype)
540+
STRUCT_FOR_ID(nt)
540541
STRUCT_FOR_ID(null)
541542
STRUCT_FOR_ID(number)
542543
STRUCT_FOR_ID(obj)
@@ -575,6 +576,7 @@ struct _Py_global_strings {
575576
STRUCT_FOR_ID(pos)
576577
STRUCT_FOR_ID(pos1)
577578
STRUCT_FOR_ID(pos2)
579+
STRUCT_FOR_ID(posix)
578580
STRUCT_FOR_ID(print_file_and_line)
579581
STRUCT_FOR_ID(priority)
580582
STRUCT_FOR_ID(progress)

Include/internal/pycore_os.h

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef Py_INTERNAL_OS_H
2+
#define Py_INTERNAL_OS_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
12+
#ifndef MS_WINDOWS
13+
#define _OS_NEED_TICKS_PER_SECOND
14+
# define need_ticks_per_second_STATE \
15+
long ticks_per_second;
16+
# define need_ticks_per_second_INIT \
17+
.ticks_per_second = -1,
18+
#else
19+
# define need_ticks_per_second_STATE
20+
# define need_ticks_per_second_INIT
21+
#endif /* MS_WINDOWS */
22+
23+
24+
struct _os_runtime_state {
25+
int _not_used;
26+
need_ticks_per_second_STATE
27+
};
28+
# define _OS_RUNTIME_INIT \
29+
{ \
30+
._not_used = 0, \
31+
need_ticks_per_second_INIT \
32+
}
33+
34+
35+
#ifdef __cplusplus
36+
}
37+
#endif
38+
#endif /* !Py_INTERNAL_OS_H */

Include/internal/pycore_runtime.h

+2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern "C" {
2121
#include "pycore_pymem.h" // struct _pymem_allocators
2222
#include "pycore_pyhash.h" // struct pyhash_runtime_state
2323
#include "pycore_obmalloc.h" // struct obmalloc_state
24+
#include "pycore_os.h" // struct _os_runtime_state
2425
#include "pycore_unicodeobject.h" // struct _Py_unicode_runtime_ids
2526

2627
struct _getargs_runtime_state {
@@ -103,6 +104,7 @@ typedef struct pyruntimestate {
103104
* KeyboardInterrupt exception, suggesting the user pressed ^C. */
104105
int unhandled_keyboard_interrupt;
105106
} signals;
107+
struct _os_runtime_state os;
106108

107109
struct pyinterpreters {
108110
PyThread_type_lock mutex;

Include/internal/pycore_runtime_init.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ extern "C" {
2626
}, \
2727
.obmalloc = _obmalloc_state_INIT(runtime.obmalloc), \
2828
.pyhash_state = pyhash_state_INIT, \
29+
.os = _OS_RUNTIME_INIT, \
2930
.interpreters = { \
3031
/* This prevents interpreters from getting created \
3132
until _PyInterpreterState_Enable() is called. */ \

Include/internal/pycore_runtime_init_generated.h

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_unicodeobject_generated.h

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_os.py

+7-6
Original file line numberDiff line numberDiff line change
@@ -606,12 +606,13 @@ def test_stat_attributes_bytes(self):
606606
def test_stat_result_pickle(self):
607607
result = os.stat(self.fname)
608608
for proto in range(pickle.HIGHEST_PROTOCOL + 1):
609-
p = pickle.dumps(result, proto)
610-
self.assertIn(b'stat_result', p)
611-
if proto < 4:
612-
self.assertIn(b'cos\nstat_result\n', p)
613-
unpickled = pickle.loads(p)
614-
self.assertEqual(result, unpickled)
609+
with self.subTest(f'protocol {proto}'):
610+
p = pickle.dumps(result, proto)
611+
self.assertIn(b'stat_result', p)
612+
if proto < 4:
613+
self.assertIn(b'cos\nstat_result\n', p)
614+
unpickled = pickle.loads(p)
615+
self.assertEqual(result, unpickled)
615616

616617
@unittest.skipUnless(hasattr(os, 'statvfs'), 'test needs os.statvfs()')
617618
def test_statvfs_attributes(self):

Makefile.pre.in

+1
Original file line numberDiff line numberDiff line change
@@ -1654,6 +1654,7 @@ PYTHON_HEADERS= \
16541654
$(srcdir)/Include/internal/pycore_object.h \
16551655
$(srcdir)/Include/internal/pycore_obmalloc.h \
16561656
$(srcdir)/Include/internal/pycore_obmalloc_init.h \
1657+
$(srcdir)/Include/internal/pycore_os.h \
16571658
$(srcdir)/Include/internal/pycore_pathconfig.h \
16581659
$(srcdir)/Include/internal/pycore_pyarena.h \
16591660
$(srcdir)/Include/internal/pycore_pyerrors.h \

Modules/posixmodule.c

+38-16
Original file line numberDiff line numberDiff line change
@@ -495,9 +495,11 @@ extern char *ctermid_r(char *);
495495
#ifdef MS_WINDOWS
496496
# define INITFUNC PyInit_nt
497497
# define MODNAME "nt"
498+
# define MODNAME_OBJ &_Py_ID(nt)
498499
#else
499500
# define INITFUNC PyInit_posix
500501
# define MODNAME "posix"
502+
# define MODNAME_OBJ &_Py_ID(posix)
501503
#endif
502504

503505
#if defined(__sun)
@@ -974,6 +976,7 @@ typedef struct {
974976
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)
975977
PyObject *SchedParamType;
976978
#endif
979+
newfunc statresult_new_orig;
977980
PyObject *StatResultType;
978981
PyObject *StatVFSResultType;
979982
PyObject *TerminalSizeType;
@@ -2225,14 +2228,25 @@ static PyStructSequence_Desc waitid_result_desc = {
22252228
5
22262229
};
22272230
#endif
2228-
static newfunc structseq_new;
22292231

22302232
static PyObject *
22312233
statresult_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
22322234
{
22332235
PyStructSequence *result;
22342236
int i;
22352237

2238+
// ht_module doesn't get set in PyStructSequence_NewType(),
2239+
// so we can't use PyType_GetModule().
2240+
PyObject *mod = PyImport_GetModule(MODNAME_OBJ);
2241+
if (mod == NULL) {
2242+
return NULL;
2243+
}
2244+
_posixstate *state = get_posix_state(mod);
2245+
if (state == NULL) {
2246+
return NULL;
2247+
}
2248+
#define structseq_new state->statresult_new_orig
2249+
22362250
result = (PyStructSequence*)structseq_new(type, args, kwds);
22372251
if (!result)
22382252
return NULL;
@@ -9051,10 +9065,23 @@ build_times_result(PyObject *module, double user, double system,
90519065
}
90529066

90539067

9054-
#ifndef MS_WINDOWS
9055-
#define NEED_TICKS_PER_SECOND
9056-
static long ticks_per_second = -1;
9057-
#endif /* MS_WINDOWS */
9068+
#ifdef _OS_NEED_TICKS_PER_SECOND
9069+
#define ticks_per_second _PyRuntime.os.ticks_per_second
9070+
static void
9071+
ticks_per_second_init(void)
9072+
{
9073+
if (ticks_per_second != -1) {
9074+
return;
9075+
}
9076+
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
9077+
ticks_per_second = sysconf(_SC_CLK_TCK);
9078+
# elif defined(HZ)
9079+
ticks_per_second = HZ;
9080+
# else
9081+
ticks_per_second = 60; /* magic fallback value; may be bogus */
9082+
# endif
9083+
}
9084+
#endif
90589085

90599086
/*[clinic input]
90609087
os.times
@@ -9089,10 +9116,10 @@ os_times_impl(PyObject *module)
90899116
(double)0,
90909117
(double)0);
90919118
}
9119+
#elif !defined(_OS_NEED_TICKS_PER_SECOND)
9120+
# error "missing ticks_per_second"
90929121
#else /* MS_WINDOWS */
90939122
{
9094-
9095-
90969123
struct tms t;
90979124
clock_t c;
90989125
errno = 0;
@@ -15912,7 +15939,7 @@ posixmodule_exec(PyObject *m)
1591215939
}
1591315940
PyModule_AddObject(m, "stat_result", Py_NewRef(StatResultType));
1591415941
state->StatResultType = StatResultType;
15915-
structseq_new = ((PyTypeObject *)StatResultType)->tp_new;
15942+
state->statresult_new_orig = ((PyTypeObject *)StatResultType)->tp_new;
1591615943
((PyTypeObject *)StatResultType)->tp_new = statresult_new;
1591715944

1591815945
statvfs_result_desc.name = "os.statvfs_result"; /* see issue #19209 */
@@ -15922,14 +15949,9 @@ posixmodule_exec(PyObject *m)
1592215949
}
1592315950
PyModule_AddObject(m, "statvfs_result", Py_NewRef(StatVFSResultType));
1592415951
state->StatVFSResultType = StatVFSResultType;
15925-
#ifdef NEED_TICKS_PER_SECOND
15926-
# if defined(HAVE_SYSCONF) && defined(_SC_CLK_TCK)
15927-
ticks_per_second = sysconf(_SC_CLK_TCK);
15928-
# elif defined(HZ)
15929-
ticks_per_second = HZ;
15930-
# else
15931-
ticks_per_second = 60; /* magic fallback value; may be bogus */
15932-
# endif
15952+
15953+
#ifdef _OS_NEED_TICKS_PER_SECOND
15954+
ticks_per_second_init();
1593315955
#endif
1593415956

1593515957
#if defined(HAVE_SCHED_SETPARAM) || defined(HAVE_SCHED_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDULER) || defined(POSIX_SPAWN_SETSCHEDPARAM)

PCbuild/pythoncore.vcxproj

+1
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@
236236
<ClInclude Include="..\Include\internal\pycore_object.h" />
237237
<ClInclude Include="..\Include\internal\pycore_obmalloc.h" />
238238
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h" />
239+
<ClInclude Include="..\Include\internal\pycore_os.h" />
239240
<ClInclude Include="..\Include\internal\pycore_pathconfig.h" />
240241
<ClInclude Include="..\Include\internal\pycore_pyarena.h" />
241242
<ClInclude Include="..\Include\internal\pycore_pyerrors.h" />

PCbuild/pythoncore.vcxproj.filters

+3
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,9 @@
612612
<ClInclude Include="..\Include\internal\pycore_obmalloc_init.h">
613613
<Filter>Include\internal</Filter>
614614
</ClInclude>
615+
<ClInclude Include="..\Include\internal\pycore_os.h">
616+
<Filter>Include\internal</Filter>
617+
</ClInclude>
615618
<ClInclude Include="..\Include\internal\pycore_pathconfig.h">
616619
<Filter>Include\internal</Filter>
617620
</ClInclude>

Tools/c-analyzer/cpython/globals-to-fix.tsv

-3
Original file line numberDiff line numberDiff line change
@@ -390,9 +390,6 @@ Modules/faulthandler.c - old_stack -
390390
##-----------------------
391391
## initialized once
392392

393-
Modules/posixmodule.c os_dup2_impl dup3_works -
394-
Modules/posixmodule.c - structseq_new -
395-
Modules/posixmodule.c - ticks_per_second -
396393
Modules/timemodule.c _PyTime_GetClockWithInfo initialized -
397394
Modules/timemodule.c _PyTime_GetProcessTimeWithInfo ticks_per_second -
398395

Tools/c-analyzer/cpython/ignored.tsv

+6-2
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@ filename funcname name reason
1111
# These are effectively const.
1212

1313
##-----------------------
14-
## process-global resources - set during first init
14+
## process-global resources
1515

1616
## indicators for resource availability/capability
17+
# (set during first init)
1718
Python/bootstrap_hash.c py_getrandom getrandom_works -
1819
Python/fileutils.c - _Py_open_cloexec_works -
1920
Python/fileutils.c set_inheritable ioctl_works -
21+
# (set lazily, *after* first init)
22+
# XXX Is this thread-safe?
23+
Modules/posixmodule.c os_dup2_impl dup3_works -
2024

21-
## resource init
25+
## resource init - set during first init
2226
Python/thread.c - initialized -
2327
Python/thread_pthread.h - condattr_monotonic -
2428
# safe static buffer used during one-time initialization

0 commit comments

Comments
 (0)