diff --git a/Misc/NEWS.d/next/Library/2026-07-13-10-37-32.gh-issue-153020.eventTs.rst b/Misc/NEWS.d/next/Library/2026-07-13-10-37-32.gh-issue-153020.eventTs.rst new file mode 100644 index 00000000000000..1dd8485ade4620 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2026-07-13-10-37-32.gh-issue-153020.eventTs.rst @@ -0,0 +1,2 @@ +Fix a data race in :mod:`!_tkinter` input event handling in free-threaded +builds. diff --git a/Modules/_tkinter.c b/Modules/_tkinter.c index f5fb1841f0d594..2fbafba27435c1 100644 --- a/Modules/_tkinter.c +++ b/Modules/_tkinter.c @@ -3655,7 +3655,7 @@ EventHook(void) int tfile; stdin_ready = 0; #endif - PyEval_RestoreThread(event_tstate); + PyEval_RestoreThread(_Py_atomic_load_ptr(&event_tstate)); errorInCmd = 0; #ifdef MS_WINDOWS hStdin = GetStdHandle(STD_INPUT_HANDLE); @@ -3687,7 +3687,7 @@ EventHook(void) #endif Py_BEGIN_ALLOW_THREADS if(tcl_lock)PyThread_acquire_lock(tcl_lock, 1); - tcl_tstate = event_tstate; + tcl_tstate = _Py_atomic_load_ptr(&event_tstate); result = Tcl_DoOneEvent(TCL_DONT_WAIT); @@ -3725,7 +3725,7 @@ EnableEventHook(void) { #ifdef WAIT_FOR_STDIN if (PyOS_InputHook == NULL) { - event_tstate = PyThreadState_Get(); + _Py_atomic_store_ptr(&event_tstate, PyThreadState_Get()); PyOS_InputHook = EventHook; } #endif @@ -3737,6 +3737,7 @@ DisableEventHook(void) #ifdef WAIT_FOR_STDIN if (Tk_GetNumMainWindows() == 0 && PyOS_InputHook == EventHook) { PyOS_InputHook = NULL; + _Py_atomic_store_ptr(&event_tstate, NULL); } #endif }