Data race creating Tcl interpreters concurrently via `_tkinter.create` under free-threading
まだ誰も着手していません。
- 主要言語
- Python
- スター
- 77.2k
- フォーク
- 35.9k
- PR マージ指標
- PR 指標を取得中
説明
Bug report
Bug description:
_tkinter declares Py_MOD_GIL_NOT_USED, so under --disable-gil the GIL no longer serializes calls into it. _tkinter.create() creates a new Tcl interpreter with Tcl_CreateInterp():
reached from _tkinter_create_impl:
_tkinter does not serialize interpreter creation, so two threads calling _tkinter.create() run Tcl_CreateInterp() concurrently. That triggers Tcl's first-time global initialization, where Tcl_MutexLock lazily initializes a static mutex. That init is not concurrency-safe, so one thread's pthread_mutex_init (write) races with another thread's pthread_mutex_lock (atomic read) on the same Tcl global.
Reproducer:
import _tkinter
from threading import Thread
def worker():
for _ in range(20000):
try:
_tkinter.create(None, '', 'Tk', False, 1, False, False, None)
except Exception:
pass
ts = [Thread(target=worker) for _ in range(12)]
for t in ts: t.start()
for t in ts: t.join()
TSAN Report (Tested on Linux, Tcl 8.6.14, with useTk=False):
==================
WARNING: ThreadSanitizer: data race (pid=650542)
Atomic read of size 1 at 0x72a0000145d0 by thread T2:
#0 pthread_mutex_lock <null>
#1 TclCreateExecEnv /usr/src/tcl8.6-8.6.14+dfsg-1build1/generic/tclExecute.c:936:5
#2 cfunction_vectorcall_FASTCALL /cpython/Objects/methodobject.c:449:24
#3 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11
#4 PyObject_Vectorcall /cpython/Objects/call.c:327:12
#5 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:768:11
#6 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1906:35
Previous write of size 1 at 0x72a0000145d0 by thread T1 (mutexes: write M0):
#0 pthread_mutex_init <null>
#1 Tcl_MutexLock /usr/src/tcl8.6-8.6.14+dfsg-1build1/unix/tclUnixThrd.c:430:6
#2 cfunction_vectorcall_FASTCALL /cpython/Objects/methodobject.c:449:24
#3 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11
#4 PyObject_Vectorcall /cpython/Objects/call.c:327:12
#5 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:768:11
#6 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1906:35
Location is heap block of size 16384 at 0x72a000014000 allocated by thread T1:
#0 malloc <null>
#1 GetBlocks /usr/src/tcl8.6-8.6.14+dfsg-1build1/generic/tclThreadAlloc.c:1044:17
#2 cfunction_vectorcall_FASTCALL /cpython/Objects/methodobject.c:449:24
#3 _PyObject_VectorcallTstate /cpython/./Include/internal/pycore_call.h:144:11
#4 PyObject_Vectorcall /cpython/Objects/call.c:327:12
#5 _Py_VectorCallInstrumentation_StackRefSteal /cpython/Python/ceval.c:768:11
#6 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:1906:35
Mutex M0 (0x7fffb1dff7a0) created at:
#0 pthread_mutex_lock <null>
#1 Tcl_MutexLock /usr/src/tcl8.6-8.6.14+dfsg-1build1/unix/tclUnixThrd.c:423:2
#2 _PyImport_RunModInitFunc /cpython/./Python/importdl.c:436:19
#3 import_run_extension /cpython/Python/import.c:2167:14
#4 _imp_create_dynamic_impl /cpython/Python/import.c:5565:11
#5 _imp_create_dynamic /cpython/Python/clinic/import.c.h:489:20
#6 cfunction_vectorcall_FASTCALL /cpython/Objects/methodobject.c:449:24
#7 _PyVectorcall_Call /cpython/Objects/call.c:273:16
#8 _PyObject_Call /cpython/Objects/call.c:348:16
#9 PyObject_Call /cpython/Objects/call.c:373:12
#10 _PyEval_EvalFrameDefault /cpython/Python/generated_cases.c.h:2831:38
SUMMARY: ThreadSanitizer: data race (/cpython/cpython-tsan/bin/python3.16t+0xfad6e) in pthread_mutex_lock
==================
On macOS with Tcl/Tk 9.0 the same reproducer surfaces the _tkinter module-global data races (PyOS_InputHook, tcl_lock). With useTk=True it crashes inside Tk's own display initialization.
CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
- gh-156342
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
Modules/_tkinter.c の Tcl_CreateInterp と _tkinter_create_impl から始め、ThreadSanitizer を使う free-threaded CPython ビルドで並行呼び出しを再現します。Linux の Tcl の race と、報告で説明されている macOS のモジュールグローバルの race を比較します。指定された reproducer でインタープリターの作成時に特定された race が報告されず、クラッシュもしなくなれば完了です。コンテキストとして gh-156342 はすでにリンクされています。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- c, python
- 領域
- desktop, operating-systems
- issue の種類
- バグ
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 活発さ
- 停滞
- 明瞭さ
- おおむね明確
- 初心者へのやさしさ
- 35/100