diff options
| author | shadchin <[email protected]> | 2026-05-07 07:27:37 +0300 |
|---|---|---|
| committer | shadchin <[email protected]> | 2026-05-07 07:57:26 +0300 |
| commit | cdd663c58847eced4c810b05edda251c70a10438 (patch) | |
| tree | 268b4bf9860a9c77564d93a803d7ecfedd3586cd /contrib/tools/python3/Python/gc.c | |
| parent | b6f47db70a8a8e904e3f38bed557097ff00f0b3b (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.c | 26 |
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. |
