File tree Expand file tree Collapse file tree 2 files changed +13
-10
lines changed
Expand file tree Collapse file tree 2 files changed +13
-10
lines changed Original file line number Diff line number Diff line change @@ -52,10 +52,6 @@ def test_atexit_instances(self):
5252 @unittest .skipUnless (support .Py_GIL_DISABLED , "only meaningful without the GIL" )
5353 def test_atexit_thread_safety (self ):
5454 # GH-126907: atexit was not thread safe on the free-threaded build
55-
56- # I'm not certain this needs to be in a script runner, but
57- # let's do it anyway.
58- code = textwrap .dedent ("""
5955 from threading import Thread
6056
6157 def dummy ():
@@ -70,10 +66,9 @@ def thready():
7066 atexit .unregister (dummy )
7167
7268
73- for x in range(100):
74- Thread(target=thready, args=()).start()
75- """ )
76- script_helper .assert_python_ok ("-c" , code )
69+ threads = [Thread (target = thready ) for _ in range (100 )]
70+ with threading_helper .start_threads (threads ):
71+ pass
7772
7873
7974@support .cpython_only
Original file line number Diff line number Diff line change @@ -62,9 +62,12 @@ atexit_delete_cb(struct atexit_state *state, int i)
6262 atexit_py_callback * cb = state -> callbacks [i ];
6363 state -> callbacks [i ] = NULL ;
6464
65+ // This can execute code via finalizers
66+ _PyAtExit_UNLOCK (state );
6567 Py_DECREF (cb -> func );
6668 Py_DECREF (cb -> args );
6769 Py_XDECREF (cb -> kwargs );
70+ _PyAtExit_LOCK (state );
6871 PyMem_Free (cb );
6972}
7073
@@ -143,8 +146,12 @@ atexit_callfuncs(struct atexit_state *state)
143146 }
144147
145148 // bpo-46025: Increment the refcount of cb->func as the call itself may unregister it
146- PyObject * the_func = Py_NewRef (cb -> func );
147- PyObject * res = PyObject_Call (cb -> func , cb -> args , cb -> kwargs );
149+ PyObject * the_func = Py_NewRef (cb -> func );
150+ PyObject * the_args = cb -> args ;
151+ PyObject * the_kwargs = cb -> kwargs ;
152+ // Unlock for re-entrancy problems
153+ _PyAtExit_UNLOCK (state );
154+ PyObject * res = PyObject_Call (the_func , the_args , the_kwargs );
148155 if (res == NULL ) {
149156 PyErr_FormatUnraisable (
150157 "Exception ignored in atexit callback %R" , the_func );
@@ -153,6 +160,7 @@ atexit_callfuncs(struct atexit_state *state)
153160 Py_DECREF (res );
154161 }
155162 Py_DECREF (the_func );
163+ _PyAtExit_LOCK (state );
156164 }
157165
158166 atexit_cleanup (state );
You can’t perform that action at this time.
0 commit comments