summaryrefslogtreecommitdiffstats
path: root/Objects/weakrefobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/weakrefobject.c')
-rw-r--r--Objects/weakrefobject.c28
1 files changed, 25 insertions, 3 deletions
diff --git a/Objects/weakrefobject.c b/Objects/weakrefobject.c
index 54fe446..6da8192 100644
--- a/Objects/weakrefobject.c
+++ b/Objects/weakrefobject.c
@@ -747,13 +747,23 @@ PyWeakref_NewRef(PyObject *ob, PyObject *callback)
them. */
result = new_weakref(ob, callback);
if (result != NULL) {
+ get_basic_refs(*list, &ref, &proxy);
if (callback == NULL) {
- insert_head(result, list);
+ if (ref == NULL)
+ insert_head(result, list);
+ else {
+ /* Someone else added a ref without a callback
+ during GC. Return that one instead of this one
+ to avoid violating the invariants of the list
+ of weakrefs for ob. */
+ Py_DECREF(result);
+ Py_INCREF(ref);
+ result = ref;
+ }
}
else {
PyWeakReference *prev;
- get_basic_refs(*list, &ref, &proxy);
prev = (proxy == NULL) ? ref : proxy;
if (prev == NULL)
insert_head(result, list);
@@ -803,8 +813,18 @@ PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
else
result->ob_type = &_PyWeakref_ProxyType;
get_basic_refs(*list, &ref, &proxy);
- if (callback == NULL)
+ if (callback == NULL) {
+ if (proxy != NULL) {
+ /* Someone else added a proxy without a callback
+ during GC. Return that one instead of this one
+ to avoid violating the invariants of the list
+ of weakrefs for ob. */
+ Py_DECREF(result);
+ Py_INCREF(result = proxy);
+ goto skip_insert;
+ }
prev = ref;
+ }
else
prev = (proxy == NULL) ? ref : proxy;
@@ -812,6 +832,8 @@ PyWeakref_NewProxy(PyObject *ob, PyObject *callback)
insert_head(result, list);
else
insert_after(result, prev);
+ skip_insert:
+ ;
}
}
return (PyObject *) result;