10000 Make PyWeakref_NewRef thread-safe · python/cpython@75603c1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 75603c1

Browse files
committed
Make PyWeakref_NewRef thread-safe
1 parent 9bf3820 commit 75603c1

File tree

1 file changed

+16
-1
lines changed

1 file changed

+16
-1
lines changed

Objects/weakrefobject.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ init_weakref(PyWeakReference *self, PyObject *ob, PyObject *callback)
3333
self->wr_next = NULL;
3434
self->wr_callback = Py_XNewRef(callback);
3535
self->vectorcall = weakref_vectorcall;
36+
#ifdef Py_GIL_DISABLED
37+
_PyObject_SetMaybeWeakref(ob);
38+
_PyObject_SetMaybeWeakref((PyObject *)self);
39+
#endif
3640
}
3741

3842
static PyWeakReference *
@@ -792,22 +796,32 @@ PyWeakref_NewRef(PyObject *ob, PyObject *callback)
792796
return NULL;
793797
}
794798
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);
795804
get_basic_refs(*list, &< E436 span class=pl-s1>ref, &proxy);
796805
if (callback == Py_None)
797806
callback = NULL;
798807
if (callback == NULL)
799808
/* return existing weak reference if it exists */
800809
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
801815
if (result != NULL)
802816
Py_INCREF(result);
803817
else {
818+
#endif
804819
/* We do not need to recompute ref/proxy; new_weakref() cannot
805820
trigger GC.
806821
*/
807822
result = new_weakref(ob, callback);
808823
if (result != NULL) {
809824
if (callback == NULL) {
810-
assert(ref == NULL);
811825
insert_head(result, list);
812826
}
813827
else {
@@ -821,6 +835,7 @@ PyWeakref_NewRef(PyObject *ob, PyObject *callback)
821835
}
822836
}
823837
}
838+
Py_END_CRITICAL_SECTION();
824839
return (PyObject *) result;
825840
}
826841

0 commit comments

Comments
 (0)
0