summaryrefslogtreecommitdiffstats
path: root/Python/gc_free_threading.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/gc_free_threading.c')
-rw-r--r--Python/gc_free_threading.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/Python/gc_free_threading.c b/Python/gc_free_threading.c
index 1e02db0..543bee2 100644
--- a/Python/gc_free_threading.c
+++ b/Python/gc_free_threading.c
@@ -55,6 +55,7 @@ struct collection_state {
struct visitor_args base;
PyInterpreterState *interp;
GCState *gcstate;
+ _PyGC_Reason reason;
Py_ssize_t collected;
Py_ssize_t uncollectable;
Py_ssize_t long_lived_total;
@@ -572,6 +573,16 @@ scan_heap_visitor(const mi_heap_t *heap, const mi_heap_area_t *area,
worklist_push(&state->unreachable, op);
}
}
+ else if (state->reason == _Py_GC_REASON_SHUTDOWN &&
+ _PyObject_HasDeferredRefcount(op))
+ {
+ // Disable deferred refcounting for reachable objects as well during
+ // interpreter shutdown. This ensures that these objects are collected
+ // immediately when their last reference is removed.
+ disable_deferred_refcounting(op);
+ merge_refcount(op, 0);
+ state->long_lived_total++;
+ }
else {
// object is reachable, restore `ob_tid`; we're done with these objects
gc_restore_tid(op);
@@ -1228,6 +1239,7 @@ gc_collect_main(PyThreadState *tstate, int generation, _PyGC_Reason reason)
struct collection_state state = {
.interp = interp,
.gcstate = gcstate,
+ .reason = reason,
};
gc_collect_internal(interp, &state, generation);