Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 3094372

Browse filesBrowse files
committed
gh-127266: avoid data races when updating type slots
In the free-threaded build, avoid data races caused by updating type slots or type flags after the type was initially created. For those (typically rare) cases, use the stop-the-world mechanism. Remove the use of atomics when reading or writing type flags. The use of atomics is not sufficient to avoid races (since flags are sometimes read without a lock and without atomics) and are no longer required.
1 parent 42b0b06 commit 3094372
Copy full SHA for 3094372

File tree

Expand file treeCollapse file tree

9 files changed

+230
-110
lines changed
Filter options
Expand file treeCollapse file tree

9 files changed

+230
-110
lines changed

‎Include/internal/pycore_interp_structs.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_interp_structs.h
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,8 +667,11 @@ struct _Py_interp_cached_objects {
667667

668668
/* object.__reduce__ */
669669
PyObject *objreduce;
670+
#ifndef Py_GIL_DISABLED
671+
/* resolve_slotdups() */
670672
PyObject *type_slots_pname;
671673
pytype_slotdef *type_slots_ptrs[MAX_EQUIV];
674+
#endif
672675

673676
/* TypeVar and related types */
674677
PyTypeObject *generic_type;

‎Include/internal/pycore_object.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_object.h
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ extern int _PyDict_CheckConsistency(PyObject *mp, int check_content);
313313
// Fast inlined version of PyType_HasFeature()
314314
static inline int
315315
_PyType_HasFeature(PyTypeObject *type, unsigned long feature) {
316-
return ((FT_ATOMIC_LOAD_ULONG_RELAXED(type->tp_flags) & feature) != 0);
316+
return ((type->tp_flags) & feature) != 0;
317317
}
318318

319319
extern void _PyType_InitCache(PyInterpreterState *interp);

‎Include/internal/pycore_typeobject.h

Copy file name to clipboardExpand all lines: Include/internal/pycore_typeobject.h
-1Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,6 @@ extern int _PyType_AddMethod(PyTypeObject *, PyMethodDef *);
134134
extern void _PyType_SetFlagsRecursive(PyTypeObject *self, unsigned long mask,
135135
unsigned long flags);
136136

137-
extern unsigned int _PyType_GetVersionForCurrentState(PyTypeObject *tp);
138137
PyAPI_FUNC(void) _PyType_SetVersion(PyTypeObject *tp, unsigned int version);
139138
PyTypeObject *_PyType_LookupByVersion(unsigned int version);
140139

‎Include/object.h

Copy file name to clipboardExpand all lines: Include/object.h
+7-5Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,12 @@ given type object has a specified feature.
620620
#define Py_TPFLAGS_HAVE_FINALIZE (1UL << 0)
621621
#define Py_TPFLAGS_HAVE_VERSION_TAG (1UL << 18)
622622

623+
// Flag values for ob_flags (16 bits available, if SIZEOF_VOID_P > 4).
624+
#define _Py_IMMORTAL_FLAGS (1 << 0)
625+
#define _Py_STATICALLY_ALLOCATED_FLAG (1 << 2)
626+
#if defined(Py_GIL_DISABLED) && defined(Py_DEBUG)
627+
#define _Py_TYPE_REVEALED_FLAG (1 << 3)
628+
#endif
623629

624630
#define Py_CONSTANT_NONE 0
625631
#define Py_CONSTANT_FALSE 1
@@ -776,11 +782,7 @@ PyType_HasFeature(PyTypeObject *type, unsigned long feature)
776782
// PyTypeObject is opaque in the limited C API
777783
flags = PyType_GetFlags(type);
778784
#else
779-
# ifdef Py_GIL_DISABLED
780-
flags = _Py_atomic_load_ulong_relaxed(&type->tp_flags);
781-
# else
782-
flags = type->tp_flags;
783-
# endif
785+
flags = type->tp_flags;
784786
#endif
785787
return ((flags & feature) != 0);
786788
}

‎Include/refcount.h

Copy file name to clipboardExpand all lines: Include/refcount.h
-3Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,6 @@ immortal. The latter should be the only instances that require
1919
cleanup during runtime finalization.
2020
*/
2121

22-
#define _Py_STATICALLY_ALLOCATED_FLAG 4
23-
#define _Py_IMMORTAL_FLAGS 1
24-
2522
#if SIZEOF_VOID_P > 4
2623
/*
2724
In 64+ bit systems, any object whose 32 bit reference count is >= 2**31
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
In the free-threaded build, avoid data races caused by updating type slots
2+
or type flags after the type was initially created. For those (typically
3+
rare) cases, use the stop-the-world mechanism. Remove the use of atomics
4+
when reading or writing type flags. The use of atomics is not sufficient to
5+
avoid races (since flags are sometimes read without a lock and without
6+
atomics) and are no longer required.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.