aboutsummaryrefslogtreecommitdiff
path: root/lang/python23/files/patch-Modules::gcmodule.c
diff options
context:
space:
mode:
Diffstat (limited to 'lang/python23/files/patch-Modules::gcmodule.c')
-rw-r--r--lang/python23/files/patch-Modules::gcmodule.c196
1 files changed, 0 insertions, 196 deletions
diff --git a/lang/python23/files/patch-Modules::gcmodule.c b/lang/python23/files/patch-Modules::gcmodule.c
deleted file mode 100644
index ef557f981eed..000000000000
--- a/lang/python23/files/patch-Modules::gcmodule.c
+++ /dev/null
@@ -1,196 +0,0 @@
---- Modules/gcmodule.c.orig Fri Apr 18 02:29:21 2003
-+++ Modules/gcmodule.c Fri Nov 21 11:39:52 2003
-@@ -377,13 +377,17 @@
- return 0;
- }
-
--/* Move the objects in unreachable with __del__ methods into finalizers.
-- * The objects remaining in unreachable do not have __del__ methods, and
-- * gc_refs remains GC_TENTATIVELY_UNREACHABLE for them. The objects
-- * moved into finalizers have gc_refs changed to GC_REACHABLE.
-+/* Move the objects in unreachable with __del__ methods into finalizers,
-+ * and weakrefs with callbacks into wr_callbacks.
-+ * The objects remaining in unreachable do not have __del__ methods, and are
-+ * not weakrefs with callbacks.
-+ * The objects moved have gc_refs changed to GC_REACHABLE; the objects
-+ * remaining in unreachable are left at GC_TENTATIVELY_UNREACHABLE.
- */
- static void
--move_finalizers(PyGC_Head *unreachable, PyGC_Head *finalizers)
-+move_troublemakers(PyGC_Head *unreachable,
-+ PyGC_Head *finalizers,
-+ PyGC_Head *wr_callbacks)
- {
- PyGC_Head *gc = unreachable->gc.gc_next;
-
-@@ -398,6 +402,12 @@
- gc_list_append(gc, finalizers);
- gc->gc.gc_refs = GC_REACHABLE;
- }
-+ else if (PyWeakref_Check(op) &&
-+ ((PyWeakReference *)op)->wr_callback) {
-+ gc_list_remove(gc);
-+ gc_list_append(gc, wr_callbacks);
-+ gc->gc.gc_refs = GC_REACHABLE;
-+ }
- gc = next;
- }
- }
-@@ -434,6 +444,93 @@
- }
- }
-
-+/* Clear all trash weakrefs with callbacks. This clears weakrefs first,
-+ * which has the happy result of disabling the callbacks without executing
-+ * them. A nasty technical complication: a weakref callback can itself be
-+ * the target of a weakref, in which case decrefing the callback can cause
-+ * another callback to trigger. But we can't allow arbitrary Python code to
-+ * get executed at this point (the callback on the callback may try to muck
-+ * with other cyclic trash we're trying to collect, even resurrecting it
-+ * while we're in the middle of doing tp_clear() on the trash).
-+ *
-+ * The private _PyWeakref_ClearRef() function exists so that we can clear
-+ * the reference in a weakref without triggering a callback on the callback.
-+ *
-+ * We have to save the callback objects and decref them later. But we can't
-+ * allocate new memory to save them (if we can't get new memory, we're dead).
-+ * So we grab a new reference on the clear'ed weakref, which prevents the
-+ * rest of gc from reclaiming it. _PyWeakref_ClearRef() leaves the
-+ * weakref's wr_callback member intact.
-+ *
-+ * In the end, then, wr_callbacks consists of cleared weakrefs that are
-+ * immune from collection. Near the end of gc, after collecting all the
-+ * cyclic trash, we call release_weakrefs(). That releases our references
-+ * to the cleared weakrefs, which in turn may trigger callbacks on their
-+ * callbacks.
-+ */
-+static void
-+clear_weakrefs(PyGC_Head *wr_callbacks)
-+{
-+ PyGC_Head *gc = wr_callbacks->gc.gc_next;
-+
-+ for (; gc != wr_callbacks; gc = gc->gc.gc_next) {
-+ PyObject *op = FROM_GC(gc);
-+ PyWeakReference *wr;
-+
-+ assert(IS_REACHABLE(op));
-+ assert(PyWeakref_Check(op));
-+ wr = (PyWeakReference *)op;
-+ assert(wr->wr_callback != NULL);
-+ Py_INCREF(op);
-+ _PyWeakref_ClearRef(wr);
-+ }
-+}
-+
-+/* Called near the end of gc. This gives up the references we own to
-+ * cleared weakrefs, allowing them to get collected, and in turn decref'ing
-+ * their callbacks.
-+ *
-+ * If a callback object is itself the target of a weakref callback,
-+ * decref'ing the callback object may trigger that other callback. If
-+ * that other callback was part of the cyclic trash in this generation,
-+ * that won't happen, since we cleared *all* trash-weakref callbacks near
-+ * the start of gc. If that other callback was not part of the cyclic trash
-+ * in this generation, then it acted like an external root to this round
-+ * of gc, so all the objects reachable from that callback are still alive.
-+ *
-+ * Giving up the references to the weakref objects will probably make
-+ * them go away too. However, if a weakref is reachable from finalizers,
-+ * it won't go away. We move it to the old generation then. Since a
-+ * weakref object doesn't have a finalizer, that's the right thing to do (it
-+ * doesn't belong in gc.garbage).
-+ *
-+ * We return the number of weakref objects freed (those not appended to old).
-+ */
-+static int
-+release_weakrefs(PyGC_Head *wr_callbacks, PyGC_Head *old)
-+{
-+ int num_freed = 0;
-+
-+ while (! gc_list_is_empty(wr_callbacks)) {
-+ PyGC_Head *gc = wr_callbacks->gc.gc_next;
-+ PyObject *op = FROM_GC(gc);
-+ PyWeakReference *wr = (PyWeakReference *)op;
-+
-+ assert(IS_REACHABLE(op));
-+ assert(PyWeakref_Check(op));
-+ assert(wr->wr_callback != NULL);
-+ Py_DECREF(op);
-+ if (wr_callbacks->gc.gc_next == gc) {
-+ /* object is still alive -- move it */
-+ gc_list_remove(gc);
-+ gc_list_append(gc, old);
-+ }
-+ else
-+ ++num_freed;
-+ }
-+ return num_freed;
-+}
-+
- static void
- debug_instance(char *msg, PyInstanceObject *inst)
- {
-@@ -535,8 +632,9 @@
- long n = 0; /* # unreachable objects that couldn't be collected */
- PyGC_Head *young; /* the generation we are examining */
- PyGC_Head *old; /* next older generation */
-- PyGC_Head unreachable;
-- PyGC_Head finalizers;
-+ PyGC_Head unreachable; /* non-problematic unreachable trash */
-+ PyGC_Head finalizers; /* objects with, & reachable from, __del__ */
-+ PyGC_Head wr_callbacks; /* weakrefs with callbacks */
- PyGC_Head *gc;
-
- if (delstr == NULL) {
-@@ -597,20 +695,33 @@
- /* All objects in unreachable are trash, but objects reachable from
- * finalizers can't safely be deleted. Python programmers should take
- * care not to create such things. For Python, finalizers means
-- * instance objects with __del__ methods.
-+ * instance objects with __del__ methods. Weakrefs with callbacks
-+ * can call arbitrary Python code, so those are special-cased too.
- *
-- * Move unreachable objects with finalizers into a different list.
-+ * Move unreachable objects with finalizers, and weakrefs with
-+ * callbacks, into different lists.
- */
- gc_list_init(&finalizers);
-- move_finalizers(&unreachable, &finalizers);
-+ gc_list_init(&wr_callbacks);
-+ move_troublemakers(&unreachable, &finalizers, &wr_callbacks);
-+ /* Clear the trash weakrefs with callbacks. This prevents their
-+ * callbacks from getting invoked (when a weakref goes away, so does
-+ * its callback).
-+ * We do this even if the weakrefs are reachable from finalizers.
-+ * If we didn't, breaking cycles in unreachable later could trigger
-+ * deallocation of objects in finalizers, which could in turn
-+ * cause callbacks to trigger. This may not be ideal behavior.
-+ */
-+ clear_weakrefs(&wr_callbacks);
- /* finalizers contains the unreachable objects with a finalizer;
-- * unreachable objects reachable only *from* those are also
-- * uncollectable, and we move those into the finalizers list too.
-+ * unreachable objects reachable *from* those are also uncollectable,
-+ * and we move those into the finalizers list too.
- */
- move_finalizer_reachable(&finalizers);
-
- /* Collect statistics on collectable objects found and print
-- * debugging information. */
-+ * debugging information.
-+ */
- for (gc = unreachable.gc.gc_next; gc != &unreachable;
- gc = gc->gc.gc_next) {
- m++;
-@@ -623,6 +734,11 @@
- * in finalizers to be freed.
- */
- delete_garbage(&unreachable, old);
-+
-+ /* Now that we're done analyzing stuff and breaking cycles, let
-+ * delayed weakref callbacks run.
-+ */
-+ m += release_weakrefs(&wr_callbacks, old);
-
- /* Collect statistics on uncollectable objects found and print
- * debugging information. */