Skip to content

Commit 1c2b4df

Browse files
gh-160682: Track running function objects in free-threaded GC
1 parent c436e8d commit 1c2b4df

2 files changed

Lines changed: 18 additions & 0 deletions

File tree

‎Lib/test/test_free_threading/test_gc.py‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ def evil():
9797
thread.start()
9898
thread.join()
9999

100+
def test_running_method_not_collected(self):
101+
class C:
102+
def m(self):
103+
wr = weakref.ref(C.__dict__["m"])
104+
del C.m
105+
gc.collect()
106+
return wr() is not None
107+
108+
def run(self):
109+
return self.m()
110+
111+
self.assertTrue(C().run())
112+
100113
def test_merge_brc_queue_of_detached_thread(self):
101114
# GH-157838: objects queued for merging by a thread that is detached
102115
# (blocked in a lock acquire, sleep, etc.) are merged and freed on its

‎Python/gc_free_threading.c‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -470,6 +470,7 @@ gc_visit_thread_stacks(PyInterpreterState *interp, struct collection_state *stat
470470
continue;
471471
}
472472

473+
gc_visit_stackref(f->f_funcobj);
473474
gc_visit_stackref(f->f_executable);
474475
while (top != f->localsplus) {
475476
--top;
@@ -866,6 +867,10 @@ gc_visit_thread_stacks_mark_alive(PyInterpreterState *interp, gc_mark_args_t *ar
866867
}
867868

868869
_PyStackRef *top = f->stackpointer;
870+
if (gc_visit_stackref_mark_alive(args, f->f_funcobj) < 0) {
871+
err = -1;
872+
goto exit;
873+
}
869874
if (gc_visit_stackref_mark_alive(args, f->f_executable) < 0) {
870875
err = -1;
871876
goto exit;

0 commit comments

Comments
 (0)