summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/Python/gc.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2026-05-07 07:27:37 +0300
committershadchin <[email protected]>2026-05-07 07:57:26 +0300
commitcdd663c58847eced4c810b05edda251c70a10438 (patch)
tree268b4bf9860a9c77564d93a803d7ecfedd3586cd /contrib/tools/python3/Python/gc.c
parentb6f47db70a8a8e904e3f38bed557097ff00f0b3b (diff)
Update Python 3 to 3.13.13
commit_hash:526db1f6570443324e2690db042314848cd47d2e
Diffstat (limited to 'contrib/tools/python3/Python/gc.c')
-rw-r--r--contrib/tools/python3/Python/gc.c26
1 files changed, 22 insertions, 4 deletions
diff --git a/contrib/tools/python3/Python/gc.c b/contrib/tools/python3/Python/gc.c
index d28cc41b20a..0397d8bad51 100644
--- a/contrib/tools/python3/Python/gc.c
+++ b/contrib/tools/python3/Python/gc.c
@@ -749,7 +749,7 @@ move_legacy_finalizer_reachable(PyGC_Head *finalizers)
* no object in `unreachable` is weakly referenced anymore.
*/
static int
-handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
+handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old, bool allow_callbacks)
{
PyGC_Head *gc;
PyObject *op; /* generally FROM_GC(gc) */
@@ -758,7 +758,9 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
PyGC_Head *next;
int num_freed = 0;
- gc_list_init(&wrcb_to_call);
+ if (allow_callbacks) {
+ gc_list_init(&wrcb_to_call);
+ }
/* Clear all weakrefs to the objects in unreachable. If such a weakref
* also has a callback, move it into `wrcb_to_call` if the callback
@@ -814,6 +816,11 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
_PyObject_ASSERT((PyObject *)wr, wr->wr_object == op);
_PyWeakref_ClearRef(wr);
_PyObject_ASSERT((PyObject *)wr, wr->wr_object == Py_None);
+
+ if (!allow_callbacks) {
+ continue;
+ }
+
if (wr->wr_callback == NULL) {
/* no callback */
continue;
@@ -866,6 +873,10 @@ handle_weakrefs(PyGC_Head *unreachable, PyGC_Head *old)
}
}
+ if (!allow_callbacks) {
+ return 0;
+ }
+
/* Invoke the callbacks we decided to honor. It's safe to invoke them
* because they can't reference unreachable objects.
*/
@@ -1401,8 +1412,7 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
}
/* Clear weakrefs and invoke callbacks as necessary. */
- m += handle_weakrefs(&unreachable, old);
-
+ m += handle_weakrefs(&unreachable, old, true);
validate_list(old, collecting_clear_unreachable_clear);
validate_list(&unreachable, collecting_set_unreachable_clear);
@@ -1415,6 +1425,14 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
PyGC_Head final_unreachable;
handle_resurrected_objects(&unreachable, &final_unreachable, old);
+ /* Clear weakrefs to objects in the unreachable set. No Python-level
+ * code must be allowed to access those unreachable objects. During
+ * delete_garbage(), finalizers outside the unreachable set might run
+ * and create new weakrefs. If those weakrefs were not cleared, they
+ * could reveal unreachable objects. Callbacks are not executed.
+ */
+ handle_weakrefs(&final_unreachable, NULL, false);
+
/* Call tp_clear on objects in the final_unreachable set. This will cause
* the reference cycles to be broken. It may also cause some objects
* in finalizers to be freed.