thp / pyotherside

Python Bindings for Qt 5 and Qt 6. Allows you to access a CPython 3 interpreter directly from your Qt QML user interface code.
https://thp.io/2011/pyotherside/
Other
364 stars 49 forks source link

App crash on removing element that called python function. #115

Open alex-eri opened 4 years ago

alex-eri commented 4 years ago

I have a StackView. Page loads data with python. If I press Cancel button with stack.pop() Page destroyed and pyotherside callback function too. So app segfaulted. How to cancel function or block component destructor?

thp commented 4 years ago

Can you provide a short, self-contained, correct example of the bug? Or at least a stack trace/back trace (e.g. by running the affected program in gdb, lldb or some other debugger)?

alex-eri commented 4 years ago

Break at 0x00002aaaa0ef8ca7 on Thread 9 QPythonWorker


Thread 17 (Thread 0x7fffb29a2700 (LWP 56063)):
#0  0x00007ffff5e95158 in pthread_cond_timedwait@@GLIBC_2.3.2 () at /usr/lib/libpthread.so.0
#1  0x00007ffff6000ce8 in QWaitCondition::wait(QMutex*, QDeadlineTimer) () at /usr/lib/libQt5Core.so.5
#2  0x00007ffff5ffefd4 in  () at /usr/lib/libQt5Core.so.5
#3  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#5  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 16 (Thread 0x7fffb21a1700 (LWP 56062)):
#0  0x00007ffff5e95158 in pthread_cond_timedwait@@GLIBC_2.3.2 () at /usr/lib/libpthread.so.0
#1  0x00007ffff6000ce8 in QWaitCondition::wait(QMutex*, QDeadlineTimer) () at /usr/lib/libQt5Core.so.5
#2  0x00007ffff5ffefd4 in  () at /usr/lib/libQt5Core.so.5
#3  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#5  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 13 (Thread 0x7fffb37fe700 (LWP 56051)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff623822c in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff5ff9c32 in QThread::exec() () at /usr/lib/libQt5Core.so.5
#6  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#7  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#8  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 12 (Thread 0x7fffb3fff700 (LWP 56050)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff6238211 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff5ff9c32 in QThread::exec() () at /usr/lib/libQt5Core.so.5
#6  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#7  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#8  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 11 (Thread 0x7fffbc819700 (LWP 56049)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff6238211 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff5ff9c32 in QThread::exec() () at /usr/lib/libQt5Core.so.5
#6  0x00007ffff79ac18b in  () at /usr/lib/libQt5Quick.so.5
#7  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#8  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#9  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 10 (Thread 0x7fffbf642700 (LWP 56048)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007fffdddcf774 in  () at /usr/lib/libnvidia-glcore.so.440.82
#2  0x00007fffddeb7a25 in  () at /usr/lib/libnvidia-glcore.so.440.82
#3  0x00007fffdddae0ce in  () at /usr/lib/libnvidia-glcore.so.440.82
#4  0x00007fffded8c1d4 in  () at /usr/lib/libGLX_nvidia.so.0
#5  0x00007fffded61071 in glXSwapBuffers () at /usr/lib/libGLX_nvidia.so.0
#6  0x00007fffe42306a9 in  () at /usr/lib/qt/plugins/xcbglintegrations/libqxcb-glx-integration.so
#7  0x00007ffff7a5cc0d in  () at /usr/lib/libQt5Quick.so.5
#8  0x00007ffff7a5d3d7 in  () at /usr/lib/libQt5Quick.so.5
#9  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#10 0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#11 0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 9 (Thread 0x7fffcca05700 (LWP 56047)):
#0  0x00002aaaa0ef8ca7 in  ()
#1  0x00007ffff620e921 in QObject::disconnect(QObject const*, char const*, QObject const*, char const*) () at /usr/lib/libQt5Core.so.5
#2  0x00007fffcf01f082 in QObjectRef::~QObjectRef() () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#3  0x00007fffcf01f09a in QObjectRef::~QObjectRef() () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#4  0x00007fffcf01af83 in pyotherside_QObject_dealloc(pyotherside_QObject*) () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#5  0x00007fffced13ddc in  () at /usr/lib/libpython3.8.so.1.0
#6  0x00007fffcf01ed6e in PyObjectRef::~PyObjectRef() () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#7  0x00007fffcf01e570 in QPythonPriv::call(_object*, QString, QVariant, QVariant*) () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#8  0x00007fffcf00edc8 in QPython::call_internal(QVariant, QVariant, bool) () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#9  0x00007fffcf01ad35 in QPythonWorker::process(QVariant, QVariant, QJSValue*) () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#10 0x00007fffcf02125c in  () at /usr/lib/qt/qml/io/thp/pyotherside/libpyothersideplugin.so
#11 0x00007ffff620c0b2 in QObject::event(QEvent*) () at /usr/lib/libQt5Core.so.5
#12 0x00007ffff61df69a in QCoreApplication::notifyInternal2(QObject*, QEvent*) () at /usr/lib/libQt5Core.so.5
#13 0x00007ffff61e2183 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) () at /usr/lib/libQt5Core.so.5
#14 0x00007ffff6238bd4 in  () at /usr/lib/libQt5Core.so.5
#15 0x00007ffff4c5043c in g_main_context_dispatch () at /usr/lib/libglib-2.0.so.0
#16 0x00007ffff4c9dfa9 in  () at /usr/lib/libglib-2.0.so.0
#17 0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#18 0x00007ffff6238211 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#19 0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#20 0x00007ffff5ff9c32 in QThread::exec() () at /usr/lib/libQt5Core.so.5
#21 0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#22 0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#23 0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 8 (Thread 0x7fffcd4e5700 (LWP 56045)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff6238211 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff5ff9c32 in QThread::exec() () at /usr/lib/libQt5Core.so.5
#6  0x00007fffe6384098 in  () at /usr/lib/libQt5DBus.so.5
#7  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#8  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#9  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 7 (Thread 0x7fffcdce6700 (LWP 56044)):
#0  0x00007ffff5e94e32 in pthread_cond_wait@@GLIBC_2.3.2 () at /usr/lib/libpthread.so.0
#1  0x00007ffff6000d64 in QWaitCondition::wait(QMutex*, QDeadlineTimer) () at /usr/lib/libQt5Core.so.5
#2  0x00007fffceb70e41 in  () at /usr/lib/qt/qml/Qt/labs/folderlistmodel/libqmlfolderlistmodelplugin.so
#3  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#5  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 6 (Thread 0x7fffceb62700 (LWP 56043)):
#0  0x00007ffff5a7a71d in syscall () at /usr/lib/libc.so.6
#1  0x00007ffff5ffd0c2 in QSemaphore::acquire(int) () at /usr/lib/libQt5Core.so.5
#2  0x00007fffe46bab4e in  () at /usr/lib/libQt5HunspellInputMethod.so.5
#3  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#5  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 5 (Thread 0x7fffdcb64700 (LWP 56042)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff6238211 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff5ff9c32 in QThread::exec() () at /usr/lib/libQt5Core.so.5
#6  0x00007ffff690a789 in  () at /usr/lib/libQt5Qml.so.5
#7  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#8  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#9  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 4 (Thread 0x7fffdf7fe700 (LWP 56041)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4ec03 in g_main_loop_run () at /usr/lib/libglib-2.0.so.0
#3  0x00007fffe50111a8 in  () at /usr/lib/libgio-2.0.so.0
#4  0x00007ffff4c78511 in  () at /usr/lib/libglib-2.0.so.0
#5  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#6  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 3 (Thread 0x7fffdffff700 (LWP 56040)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff4c4f272 in  () at /usr/lib/libglib-2.0.so.0
#4  0x00007ffff4c78511 in  () at /usr/lib/libglib-2.0.so.0
#5  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#6  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 2 (Thread 0x7fffe624f700 (LWP 56039)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff596263b in  () at /usr/lib/libxcb.so.1
#2  0x00007ffff596437b in xcb_wait_for_event () at /usr/lib/libxcb.so.1
#3  0x00007fffe6450c51 in  () at /usr/lib/libQt5XcbQpa.so.5
#4  0x00007ffff5ffae0f in  () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff5e8e422 in start_thread () at /usr/lib/libpthread.so.0
#6  0x00007ffff5a7fbf3 in clone () at /usr/lib/libc.so.6

Thread 1 (Thread 0x7ffff2a39800 (LWP 56035)):
#0  0x00007ffff5a7505f in poll () at /usr/lib/libc.so.6
#1  0x00007ffff4c9df38 in  () at /usr/lib/libglib-2.0.so.0
#2  0x00007ffff4c4f221 in g_main_context_iteration () at /usr/lib/libglib-2.0.so.0
#3  0x00007ffff6238211 in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#4  0x00007ffff61de01c in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () at /usr/lib/libQt5Core.so.5
#5  0x00007ffff61e64a4 in QCoreApplication::exec() () at /usr/lib/libQt5Core.so.5
#6  0x00005555555581d8 in main(int, char**) (argc=1, argv=0x7fffffffe6a8) at ../kiosk/main.cpp:98
        sansFont = {static staticMetaObject = {d = {superdata = {direct = 0x0}, stringdata = 0x7ffff70ec5c0, data = 0x7ffff70ec240, static_metacall = 0x0, relatedMetaObjects = 0x0, extradata = 0x0}}, d = {d = 0x5555555a7cc0}, resolve_mask = 3}
        app = <incomplete type>
        engine = <incomplete type>
        url = {d = 0x555555b1b400}
alex-eri commented 4 years ago

Another stop stack. In QPythonWorker too.

1  ??                                                                                                      
2  QMetaObject::cast(QObject const *) const                                                 0x7ffff61e852a 
3  QtPrivate::QVariantValueHelper<QObject *>::object(QVariant const&)                       0x7fffcf0183ab 
4  _object * convert<QVariant, _object *, QVariantConverter, PyObjectConverter>(QVariant)   0x7fffcf01a7ca 
5  _object * convert<QVariant, _object *, QVariantConverter, PyObjectConverter>(QVariant)   0x7fffcf01a58c 
6  QPythonPriv::call(_object *, QString, QVariant, QVariant *)                              0x7fffcf01e36d 
7  QPython::call_internal(QVariant, QVariant, bool)                                         0x7fffcf00edc8 
8  QPythonWorker::process(QVariant, QVariant, QJSValue *)                                   0x7fffcf01ad35 
9  ??                                                                                       0x7fffcf02125c 
10 QObject::event(QEvent *)                                                                 0x7ffff620c0b2 
11 QCoreApplication::notifyInternal2(QObject *, QEvent *)                                   0x7ffff61df69a 
12 QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *)                 0x7ffff61e2183 
13 ??                                                                                       0x7ffff6238bd4 
14 g_main_context_dispatch                                                                  0x7ffff4c5043c 
15 ??                                                                                       0x7ffff4c9dfa9 
16 g_main_context_iteration                                                                 0x7ffff4c4f221 
17 QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)               0x7ffff6238211 
18 QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>)                                  0x7ffff61de01c 
19 QThread::exec()                                                                          0x7ffff5ff9c32 
20 ??                                                                                       0x7ffff5ffae0f 
21 start_thread                                                                             0x7ffff5e8e422 
22 clone                                                                                    0x7ffff5a7fbf3 
alex-eri commented 4 years ago

I will provide short code in few days.

alex-eri commented 4 years ago

And with debug version of plugin

1   ??                                                                                                                          
2   QObjectData::dynamicMetaObject() const                                                                       0x7ffff6208b8d 
3   QObject::disconnect(QObject const *, const char *, QObject const *, const char *)                            0x7ffff620e921 
4   QObjectRef::~QObjectRef                                                           qobject_ref.cpp        42  0x7fffcf0118ae 
5   QObjectRef::~QObjectRef                                                           qobject_ref.cpp        45  0x7fffcf0118dc 
6   pyotherside_QObject_dealloc                                                       qpython_priv.cpp       197 0x7fffcf00d875 
7   ??                                                                                                           0x7fffcecf0ddc 
8   _Py_DECREF                                                                        object.h               478 0x7fffcf0112cd 
9   PyObjectRef::~PyObjectRef                                                         pyobject_ref.cpp       45  0x7fffcf011475 
10  QPythonPriv::call                                                                 qpython_priv.cpp       724 0x7fffcf010724 
11  QPython::call_internal                                                            qpython.cpp            377 0x7fffcf004ae7 
12  QPythonWorker::process                                                            qpython_worker.cpp     37  0x7fffcf00ccef 
13  QPythonWorker::qt_static_metacall                                                 moc_qpython_worker.cpp 98  0x7fffcf01471b 
14  QObject::event(QEvent *)                                                                                     0x7ffff620c0b2 
15  QCoreApplication::notifyInternal2(QObject *, QEvent *)                                                       0x7ffff61df69a 
16  QCoreApplicationPrivate::sendPostedEvents(QObject *, int, QThreadData *)                                     0x7ffff61e2183 
17  ??                                                                                                           0x7ffff6238bd4 
18  g_main_context_dispatch                                                                                      0x7ffff4c5043c 
19  ??                                                                                                           0x7ffff4c9dfa9 
20  g_main_context_iteration                                                                                     0x7ffff4c4f221 
... <Более>                                                                                                                     
alex-eri commented 4 years ago

no ideas how to fix it?

thp commented 4 years ago

I haven't had time to investigate yet. From a quick glance at the traces, it looks like the Python side keeps a reference to a Qt object that has since been deallocated. We DO connect to the destroyed() signal of the QObject, so that case should be handled. You could try printing something in the function QObjectRef::handleDestroyed in src/qobject_ref.cpp to see if this is done.

It could also be that there's something wrong with the implementation in QObjectRef::operator=.

In order to easily debug it here, I would still need a short, self-contained correct example of the bug (code!) that makes it easy to reproduce the issue.

thp commented 4 years ago

If it is really a use-after-free situation, maybe using https://doc.qt.io/qt-5/qpointer.html could be useful instead of a raw pointer to QObject + custom destroyed() handling.