File tree Expand file tree Collapse file tree
Lib/test/test_free_threading Expand file tree Collapse file tree Original file line number Diff line number Diff line change 11import textwrap
22import unittest
33
4+ from test import support
45from test .support import import_helper , script_helper
56
67
@@ -24,6 +25,19 @@ def test_destroy_subinterpreter_does_not_abort(self):
2425 """ )
2526 script_helper .assert_python_ok ('-c' , script )
2627
28+ @support .requires_resource ('cpu' )
29+ def test_destroy_subinterpreter_with_abandoned_pages_does_not_abort (self ):
30+ # gh-159462: Py_EndInterpreter() clears a non-current thread state.
31+ script = textwrap .dedent ("""
32+ import _testinternalcapi
33+
34+ interpid = _testinternalcapi.create_interpreter()
35+ _testinternalcapi.exec_interpreter(
36+ interpid, "objs = [[i] for i in range(400_000)]; del objs")
37+ _testinternalcapi.destroy_interpreter(interpid, basic=True)
38+ """ )
39+ script_helper .assert_python_ok ('-c' , script )
40+
2741
2842if __name__ == "__main__" :
2943 unittest .main ()
Original file line number Diff line number Diff line change @@ -212,7 +212,10 @@ _PyMem_mi_page_reclaimed(mi_page_t *page)
212212 if (mi_page_all_free (page )) {
213213 assert (page -> qsbr_node .next == NULL );
214214 _PyThreadStateImpl * tstate = tstate_from_heap (mi_page_heap (page ));
215- assert (tstate == (_PyThreadStateImpl * )_PyThreadState_GET ());
215+ // gh-159462: the owning tstate may differ from the current
216+ // one, but the heap is always owned by the current OS thread,
217+ // so the page list is not shared with other OS threads.
218+ assert (mi_page_heap (page )-> thread_id == _Py_ThreadId ());
216219 page -> retire_expire = 0 ;
217220 llist_insert_tail (& tstate -> mimalloc .page_list , & page -> qsbr_node );
218221 }
You can’t perform that action at this time.
0 commit comments