@@ -33,6 +33,10 @@ init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
33
33
self -> wr_next = NULL ;
34
34
self -> wr_callback = Py_XNewRef (callback );
35
35
self -> vectorcall = weakref_vectorcall ;
36
+ #ifdef Py_GIL_DISABLED
37
+ _PyObject_SetMaybeWeakref (ob );
38
+ _PyObject_SetMaybeWeakref ((PyObject * )self );
39
+ #endif
36
40
}
37
41
38
42
static PyWeakReference *
@@ -792,22 +796,32 @@ PyWeakref_NewRef(PyObject *ob, PyObject *callback)
792
796
return NULL ;
793
797
}
794
798
list = GET_WEAKREFS_LISTPTR (ob );
799
+ /* NB: For free-threaded builds its critical that no code inside the
800
+ * critical section can release it. We need to recompute ref/proxy after
801
+ * any code that may release the critical section.
802
+ */
803
+ Py_BEGIN_CRITICAL_SECTION (ob );
795
804
get_basic_refs (* list , & <
E436
span class=pl-s1>ref, & proxy );
796
805
if (callback == Py_None )
797
806
callback = NULL ;
798
807
if (callback == NULL )
799
808
/* return existing weak reference if it exists */
800
809
result = ref ;
810
+ #ifdef Py_GIL_DISABLED
811
+ /* Incref will fail if the existing weakref is being destroyed */
812
+ if (result == NULL ||
813
+ !_Py_TryIncref ((PyObject * * )& result , (PyObject * )result )) {
814
+ #else
801
815
if (result != NULL )
802
816
Py_INCREF (result );
803
817
else {
818
+ #endif
804
819
/* We do not need to recompute ref/proxy; new_weakref() cannot
805
820
trigger GC.
806
821
*/
807
822
result = new_weakref (ob , callback );
808
823
if (result != NULL ) {
809
824
if (callback == NULL ) {
810
- assert (ref == NULL );
811
825
insert_head (result , list );
812
826
}
813
827
else {
@@ -821,6 +835,7 @@ PyWeakref_NewRef(PyObject *ob, PyObject *callback)
821
835
}
822
836
}
823
837
}
838
+ Py_END_CRITICAL_SECTION ();
824
839
return (PyObject * ) result ;
825
840
}
826
841
0 commit comments