@@ -92,6 +92,19 @@ types_world_is_stopped(void)
9292    return  interp -> stoptheworld .world_stopped ;
9393}
9494
95+ // Checks that either the type has not yet been revealed (exposed) to 
96+ // other threads or the world is stopped and we can safely update it 
97+ // without races.  The _Py_TYPE_REVEALED_FLAG flag is set by type_new() and 
98+ // PyType_FromMetaclass() to indicate that a newly initialized type might 
99+ // be revealed. 
100+ #if  SIZEOF_VOID_P  >  4 
101+ #define  ASSERT_NEW_OR_STOPPED (tp )                                              \
102+     assert((((PyObject *)(tp))->ob_flags & _Py_TYPE_REVEALED_FLAG) == 0 ||      \
103+            types_world_is_stopped())
104+ #else 
105+ #define  ASSERT_NEW_OR_STOPPED (tp )
106+ #endif 
107+ 
95108static  void 
96109types_stop_world (void )
97110{
@@ -159,6 +172,7 @@ types_mutex_unlock(void)
159172#define  types_stop_world ()
160173#define  types_start_world ()
161174#define  ASSERT_TYPE_LOCK_HELD ()
175+ #define  ASSERT_NEW_OR_STOPPED (tp )
162176
163177#endif 
164178
@@ -428,13 +442,15 @@ type_set_flags(PyTypeObject *tp, unsigned long flags)
428442        // be active). 
429443        ASSERT_TYPE_LOCK_HELD ();
430444    }
445+     ASSERT_NEW_OR_STOPPED (tp );
431446    tp -> tp_flags  =  flags ;
432447}
433448
434449static  void 
435450type_set_flags_with_mask (PyTypeObject  * tp , unsigned long  mask , unsigned long  flags )
436451{
437452    ASSERT_TYPE_LOCK_HELD ();
453+     ASSERT_NEW_OR_STOPPED (tp );
438454    unsigned long  new_flags  =  (tp -> tp_flags  &  ~mask ) | flags ;
439455    type_set_flags (tp , new_flags );
440456}
@@ -570,6 +586,7 @@ static inline void
570586set_tp_bases (PyTypeObject  * self , PyObject  * bases , int  initial )
571587{
572588    assert (PyTuple_CheckExact (bases ));
589+     ASSERT_NEW_OR_STOPPED (self );
573590    if  (self -> tp_flags  &  _Py_TPFLAGS_STATIC_BUILTIN ) {
574591        // XXX tp_bases can probably be statically allocated for each 
575592        // static builtin type. 
@@ -627,6 +644,7 @@ _PyType_GetMRO(PyTypeObject *self)
627644static  inline  void 
628645set_tp_mro (PyTypeObject  * self , PyObject  * mro , int  initial )
629646{
647+     ASSERT_NEW_OR_STOPPED (self );
630648    if  (mro  !=  NULL ) {
631649        assert (PyTuple_CheckExact (mro ));
632650        if  (self -> tp_flags  &  _Py_TPFLAGS_STATIC_BUILTIN ) {
@@ -1705,6 +1723,7 @@ static int
17051723mro_hierarchy (PyTypeObject  * type , PyObject  * temp )
17061724{
17071725    ASSERT_TYPE_LOCK_HELD ();
1726+     ASSERT_NEW_OR_STOPPED (type );
17081727
17091728    PyObject  * old_mro ;
17101729    int  res  =  mro_internal (type , & old_mro );
@@ -3551,6 +3570,7 @@ static int
35513570mro_internal_unlocked (PyTypeObject  * type , int  initial , PyObject  * * p_old_mro )
35523571{
35533572    ASSERT_TYPE_LOCK_HELD ();
3573+     ASSERT_NEW_OR_STOPPED (type );
35543574
35553575    PyObject  * new_mro , * old_mro ;
35563576    int  reent ;
@@ -3600,6 +3620,7 @@ static int
36003620mro_internal (PyTypeObject  * type , PyObject  * * p_old_mro )
36013621{
36023622    int  res ;
3623+     ASSERT_NEW_OR_STOPPED (type );
36033624    res  =  mro_internal_unlocked (type , 0 , p_old_mro );
36043625    return  res ;
36053626}
@@ -4679,6 +4700,10 @@ type_new_impl(type_new_ctx *ctx)
46794700    }
46804701
46814702    assert (_PyType_CheckConsistency (type ));
4703+ #if  defined(Py_GIL_DISABLED ) &&  defined(Py_DEBUG ) &&  SIZEOF_VOID_P  >  4 
4704+     // After this point, other threads can potentally use this type. 
4705+     ((PyObject * )type )-> ob_flags  |= _Py_TYPE_REVEALED_FLAG ;
4706+ #endif 
46824707
46834708    return  (PyObject  * )type ;
46844709
@@ -5392,6 +5417,10 @@ PyType_FromMetaclass(
53925417    }
53935418
53945419    assert (_PyType_CheckConsistency (type ));
5420+ #if  defined(Py_GIL_DISABLED ) &&  defined(Py_DEBUG ) &&  SIZEOF_VOID_P  >  4 
5421+     // After this point, other threads can potentally use this type. 
5422+     ((PyObject * )type )-> ob_flags  |= _Py_TYPE_REVEALED_FLAG ;
5423+ #endif 
53955424
53965425 finally :
53975426    if  (PyErr_Occurred ()) {
@@ -8649,6 +8678,7 @@ static int
86498678type_ready_mro (PyTypeObject  * type , int  initial )
86508679{
86518680    ASSERT_TYPE_LOCK_HELD ();
8681+     ASSERT_NEW_OR_STOPPED (type );
86528682
86538683    if  (type -> tp_flags  &  _Py_TPFLAGS_STATIC_BUILTIN ) {
86548684        if  (!initial ) {
@@ -8724,6 +8754,7 @@ static int
87248754type_ready_inherit (PyTypeObject  * type )
87258755{
87268756    ASSERT_TYPE_LOCK_HELD ();
8757+     ASSERT_NEW_OR_STOPPED (type );
87278758
87288759    /* Inherit special flags from dominant base */ 
87298760    PyTypeObject  * base  =  type -> tp_base ;
@@ -8921,6 +8952,7 @@ static int
89218952type_ready (PyTypeObject  * type , int  initial )
89228953{
89238954    ASSERT_TYPE_LOCK_HELD ();
8955+     ASSERT_NEW_OR_STOPPED (type );
89248956
89258957    _PyObject_ASSERT ((PyObject  * )type , !is_readying (type ));
89268958    start_readying (type );
@@ -11253,6 +11285,7 @@ static pytype_slotdef *
1125311285update_one_slot (PyTypeObject  * type , pytype_slotdef  * p )
1125411286{
1125511287    ASSERT_TYPE_LOCK_HELD ();
11288+     ASSERT_NEW_OR_STOPPED (type );
1125611289
1125711290    PyObject  * descr ;
1125811291    PyWrapperDescrObject  * d ;
@@ -11369,6 +11402,7 @@ static int
1136911402update_slots_callback (PyTypeObject  * type , void  * data )
1137011403{
1137111404    ASSERT_TYPE_LOCK_HELD ();
11405+     ASSERT_NEW_OR_STOPPED (type );
1137211406
1137311407    pytype_slotdef  * * pp  =  (pytype_slotdef  * * )data ;
1137411408    for  (; * pp ; pp ++ ) {
@@ -11387,6 +11421,7 @@ update_slot(PyTypeObject *type, PyObject *name)
1138711421    int  offset ;
1138811422
1138911423    ASSERT_TYPE_LOCK_HELD ();
11424+     ASSERT_NEW_OR_STOPPED (type );
1139011425    assert (types_world_is_stopped ());
1139111426    assert (PyUnicode_CheckExact (name ));
1139211427    assert (PyUnicode_CHECK_INTERNED (name ));
@@ -11441,6 +11476,7 @@ update_all_slots(PyTypeObject* type)
1144111476    pytype_slotdef  * p ;
1144211477
1144311478    ASSERT_TYPE_LOCK_HELD ();
11479+     ASSERT_NEW_OR_STOPPED (type );
1144411480
1144511481    /* Clear the VALID_VERSION flag of 'type' and all its subclasses. */ 
1144611482    type_modified_unlocked (type );
0 commit comments