diff Objects/weakrefobject.c @ 31453:3cc3cb79043f 2.3

Allocating a new weakref object can cause existing weakref objects for the same object to be collected by the cyclic GC support if they are only referenced by a cycle. If the weakref being collected was one of the weakrefs without callbacks, some local variables for the constructor became invalid and have to be re-computed. The test caused a segfault under a debug build without the fix applied.
author Fred Drake <fdrake@acm.org>
date Wed, 04 Feb 2004 23:13:43 +0000
parents b4bc83f2fd04
children ec71ae3bc2dd 4383db77b19a
line wrap: on
line diff
--- a/Objects/weakrefobject.c	Tue Feb 03 20:50:45 2004 +0000
+++ b/Objects/weakrefobject.c	Wed Feb 04 23:13:43 2004 +0000
@@ -630,16 +630,23 @@
         /* return existing weak reference if it exists */
         result = ref;
     if (result != NULL)
-        Py_XINCREF(result);
+        Py_INCREF(result);
     else {
+        /* Note: new_weakref() can trigger cyclic GC, so the weakref
+           list on ob can be mutated.  This means that the ref and
+           proxy pointers we got back earlier may have been collected,
+           so we need to compute these values again before we use
+           them. */
         result = new_weakref(ob, callback);
         if (result != NULL) {
             if (callback == NULL) {
                 insert_head(result, list);
             }
             else {
-                PyWeakReference *prev = (proxy == NULL) ? ref : proxy;
+                PyWeakReference *prev;
 
+                get_basic_refs(*list, &ref, &proxy);
+                prev = (proxy == NULL) ? ref : proxy;
                 if (prev == NULL)
                     insert_head(result, list);
                 else
@@ -672,8 +679,13 @@
         /* attempt to return an existing weak reference if it exists */
         result = proxy;
     if (result != NULL)
-        Py_XINCREF(result);
+        Py_INCREF(result);
     else {
+        /* Note: new_weakref() can trigger cyclic GC, so the weakref
+           list on ob can be mutated.  This means that the ref and
+           proxy pointers we got back earlier may have been collected,
+           so we need to compute these values again before we use
+           them. */
         result = new_weakref(ob, callback);
         if (result != NULL) {
             PyWeakReference *prev;
@@ -682,6 +694,7 @@
                 result->ob_type = &_PyWeakref_CallableProxyType;
             else
                 result->ob_type = &_PyWeakref_ProxyType;
+            get_basic_refs(*list, &ref, &proxy);
             if (callback == NULL)
                 prev = ref;
             else