Skip to content

Commit fb1e691

Browse files
authored
gh-105927: _abc and _thread use PyWeakref_GetRef() (#105961)
Hold a strong reference on the object, rather than using a borrowed reference: replace PyWeakref_GET_OBJECT() with PyWeakref_GetRef() and _PyWeakref_GET_REF(). Remove assert(PyWeakref_CheckRef(localweakref)) since it's already tested by _PyWeakref_GET_REF().
1 parent eaa6702 commit fb1e691

File tree

2 files changed

+20
-21
lines changed

2 files changed

+20
-21
lines changed

Modules/_abc.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "pycore_object.h" // _PyType_GetSubclasses()
99
#include "pycore_runtime.h" // _Py_ID()
1010
#include "pycore_typeobject.h" // _PyType_GetMRO()
11+
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
1112
#include "clinic/_abc.c.h"
1213

1314
/*[clinic input]
@@ -150,12 +151,10 @@ _in_weak_set(PyObject *set, PyObject *obj)
150151
static PyObject *
151152
_destroy(PyObject *setweakref, PyObject *objweakref)
152153
{
153-
PyObject *set;
154-
set = PyWeakref_GET_OBJECT(setweakref);
155-
if (set == Py_None) {
154+
PyObject *set = _PyWeakref_GET_REF(setweakref);
155+
if (set == NULL) {
156156
Py_RETURN_NONE;
157157
}
158-
Py_INCREF(set);
159158
if (PySet_Discard(set, objweakref) < 0) {
160159
Py_DECREF(set);
161160
return NULL;
@@ -843,16 +842,16 @@ subclasscheck_check_registry(_abc_data *impl, PyObject *subclass,
843842
assert(i == registry_size);
844843

845844
for (i = 0; i < registry_size; i++) {
846-
PyObject *rkey = PyWeakref_GetObject(copy[i]);
847-
if (rkey == NULL) {
845+
PyObject *rkey;
846+
if (PyWeakref_GetRef(copy[i], &rkey) < 0) {
848847
// Someone inject non-weakref type in the registry.
849848
ret = -1;
850849
break;
851850
}
852-
if (rkey == Py_None) {
851+
852+
if (rkey == NULL) {
853853
continue;
854854
}
855-
Py_INCREF(rkey);
856855
int r = PyObject_IsSubclass(subclass, rkey);
857856
Py_DECREF(rkey);
858857
if (r < 0) {

Modules/_threadmodule.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "pycore_moduleobject.h" // _PyModule_GetState()
88
#include "pycore_pylifecycle.h"
99
#include "pycore_pystate.h" // _PyThreadState_SetCurrent()
10+
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
1011
#include <stddef.h> // offsetof()
1112
#include "structmember.h" // PyMemberDef
1213

@@ -1024,25 +1025,23 @@ local_getattro(localobject *self, PyObject *name)
10241025
static PyObject *
10251026
_localdummy_destroyed(PyObject *localweakref, PyObject *dummyweakref)
10261027
{
1027-
assert(PyWeakref_CheckRef(localweakref));
1028-
PyObject *obj = PyWeakref_GET_OBJECT(localweakref);
1029-
if (obj == Py_None) {
1028+
localobject *self = (localobject *)_PyWeakref_GET_REF(localweakref);
1029+
if (self == NULL) {
10301030
Py_RETURN_NONE;
10311031
}
10321032

10331033
/* If the thread-local object is still alive and not being cleared,
10341034
remove the corresponding local dict */
1035-
localobject *self = (localobject *)Py_NewRef(obj);
10361035
if (self->dummies != NULL) {
10371036
PyObject *ldict;
10381037
ldict = PyDict_GetItemWithError(self->dummies, dummyweakref);
10391038
if (ldict != NULL) {
10401039
PyDict_DelItem(self->dummies, dummyweakref);
10411040
}
10421041
if (PyErr_Occurred())
1043-
PyErr_WriteUnraisable(obj);
1042+
PyErr_WriteUnraisable((PyObject*)self);
10441043
}
1045-
Py_DECREF(obj);
1044+
Py_DECREF(self);
10461045
Py_RETURN_NONE;
10471046
}
10481047

@@ -1314,24 +1313,25 @@ This function is meant for internal and specialized purposes only.\n\
13141313
In most applications `threading.enumerate()` should be used instead.");
13151314

13161315
static void
1317-
release_sentinel(void *wr_raw)
1316+
release_sentinel(void *weakref_raw)
13181317
{
1319-
PyObject *wr = _PyObject_CAST(wr_raw);
1318+
PyObject *weakref = _PyObject_CAST(weakref_raw);
1319+
13201320
/* Tricky: this function is called when the current thread state
13211321
is being deleted. Therefore, only simple C code can safely
13221322
execute here. */
1323-
PyObject *obj = PyWeakref_GET_OBJECT(wr);
1324-
lockobject *lock;
1325-
if (obj != Py_None) {
1326-
lock = (lockobject *) obj;
1323+
lockobject *lock = (lockobject *)_PyWeakref_GET_REF(weakref);
1324+
if (lock != NULL) {
13271325
if (lock->locked) {
13281326
PyThread_release_lock(lock->lock_lock);
13291327
lock->locked = 0;
13301328
}
1329+
Py_DECREF(lock);
13311330
}
1331+
13321332
/* Deallocating a weakref with a NULL callback only calls
13331333
PyObject_GC_Del(), which can't call any Python code. */
1334-
Py_DECREF(wr);
1334+
Py_DECREF(weakref);
13351335
}
13361336

13371337
static PyObject *

0 commit comments

Comments
 (0)