我已经为PySide/Cython多线程应用程序苦苦挣扎了好几天。
将问题拆分为多个部分,我进行了一项使用 valgrind/helgrind 运行的测试(请参阅下面的一个错误条目)。
C 函数(load
下面的 CHLone)使用 Python 及其 GIL(对 Cython 没有指令),
Shiboken也访问 GIL。
输出表明与 GIL 访问存在冲突(除非我错了),但我的理解是 GIL 的存在是为了避免这种冲突。
Shiboken执行了一些与PyList_New
另一个线程冲突的 dealloc ......
我迷路了,
我以为GIL 负责阻塞 PyList_New
,而另一个线程正在修改一些 Python 共享数据。还是Shiboken忘记锁了?
第listobject.c
161 行是_PyObject_GC_TRACK()
(我假设)要求 GC 跟踪新对象的调用。
第 classobject.c
2360 行是一个_PyObject_GC_UNTRACK()
强烈要求 GC 停止跟踪对象的调用......
我看到helgrind diag 是一个可能的数据竞争,但事实上这会导致核心转储,我不喜欢使用线程时 Python GC 上可能出现的单词。我想先解决这个问题。
==26535== ----------------------------------------------------------------
==26535==
==26535== Possible data race during read of size 8 at 0x4FE8488 by thread #2
==26535== Locks held: none
==26535== at 0x4C92A80: PyList_New (listobject.c:161)
==26535== by 0x742C43F: s2p_parseAndReadHDF (SIDStoPython.c:949)
==26535== by 0x742C5C4: s2p_parseAndReadHDF (SIDStoPython.c:968)
==26535== by 0x742E638: s2p_loadAsHDF (SIDStoPython.c:1485)
==26535== by 0x741C3CC: __pyx_f_6CHLone_load (pyCHLone.c:2182)
==26535== by 0x741D2AD: __pyx_pf_6CHLone_12load (pyCHLone.c:2422)
==26535== by 0x741D1C3: __pyx_pw_6CHLone_13load (pyCHLone.c:2392)
==26535== by 0x4D0A48F: PyEval_EvalFrameEx (ceval.c:4013)
==26535== by 0x4D0C3DC: PyEval_EvalCodeEx (ceval.c:3253)
==26535== by 0x4C8B641: function_call (funcobject.c:526)
==26535== by 0x4C5F652: PyObject_Call (abstract.c:2529)
==26535== by 0x4C7279E: instancemethod_call (classobject.c:2578)
==26535==
==26535== This conflicts with a previous write of size 8 by thread #1
==26535== Locks held: none
==26535== at 0x4C6C53F: instancemethod_dealloc (classobject.c:2360)
==26535== by 0x5AB248A: Shiboken::AutoDecRef::~AutoDecRef() (in /tmp/tools-2/local/x86z/lib/python2.7/site-packages/PySide/QtCore.so)
==26535== by 0x5F9736F: PySide::GlobalReceiverV2::qt_metacall(QMetaObject::Call, int, void**) (in /tmp/tools-2/local/x86z/lib/libpyside-python2.7.so.1.0.9)
==26535== by 0x659BCA5: QObject::event(QEvent*) (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535== by 0x5B038C5: QCoreApplicationWrapper::notify(QObject*, QEvent*) (in /tmp/tools-2/local/x86z/lib/python2.7/site-packages/PySide/QtCore.so)
==26535== by 0x6586F8B: QCoreApplication::notifyInternal(QObject*, QEvent*) (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535== by 0x658A5A7: QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535== by 0x65B60F2: ??? (in /tmp/tools-2/local/x86z/lib/libQtCore.so.4.8.0)
==26535==
问题:
1. 我为 GIL 假设的行为是否正确?
2. 如果No ,
... 是否意味着我必须自己管理每个线程中的 GIL 锁?
...然后我必须为 Python 创建自己的互斥锁?!????!?
3. 如果是,
... 我的 Cython 或 C 库中是否存在关于 GIL 使用的问题?
...会不会是QThread/QMutex的副作用?