Skip to content

imobiledevice: Handle events in correct thread

Kai Uwe Broulik requested to merge work/kbroulik/imobile-callback-mutex into master

Turns out, the idevice_event_subscribe callback can be called from a different thread.

Use QMetaObject::invokeMethod to ensure the event is handled in the same thread as the manager itself.


Noticed this while doing network/kio-extras!7 (merged) and got funky crashes like

Thread 1 (Thread 0x7fd4f7dd5dc0 (LWP 31914)):
[KCrash Handler]
#6  std::__atomic_base<int>::load (__m=std::memory_order_relaxed, this=0x0) at /usr/include/c++/11/bits/atomic_base.h:479
#7  QAtomicOps<int>::loadRelaxed<int> (_q_value=<error reading variable: Cannot access memory at address 0x0>) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qatomic_cxx11.h:239
#8  QBasicAtomicInteger<int>::loadRelaxed (this=0x0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qbasicatomic.h:107
#9  QtPrivate::RefCount::ref (this=0x0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qrefcount.h:55
#10 QString::QString (other=..., this=0x55845b1d1310) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h:1094
#11 QList<QString>::node_copy (src=0x7fd4fc92e680 <QListData::shared_null+16>, to=0x55845b1d1318, from=0x55845b1d1310, this=0x55845b1d0c50) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h:505
#12 QList<QString>::detach_helper (this=0x55845b1d0c50, alloc=<optimized out>) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h:835
#13 0x00007fd4f7a1db33 in QList<QString>::reserve (alloc=<optimized out>, this=0x55845b1d0c50) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qlist.h:613
#14 Solid::Backends::IMobile::Manager::Manager (this=this@entry=0x55845b1d0c40, parent=parent@entry=0x0) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/backends/imobile/imobilemanager.cpp:40
#15 0x00007fd4f79b3ede in Solid::ManagerBasePrivate::loadBackends (this=this@entry=0x55845b1cef30) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/managerbase.cpp:64
#16 0x00007fd4f79b7358 in Solid::DeviceManagerPrivate::DeviceManagerPrivate (this=0x55845b1cef20) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/frontend/devicemanager.cpp:33
#17 0x00007fd4f79b75f5 in Solid::DeviceManagerStorage::ensureManagerCreated (this=0x7fd4f7a57000 <(anonymous namespace)::Q_QGS_globalDeviceStorage::innerFunction()::holder>) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/frontend/devicemanager.cpp:322
#18 Solid::DeviceManagerStorage::managerBackends (this=this@entry=0x7fd4f7a57000 <(anonymous namespace)::Q_QGS_globalDeviceStorage::innerFunction()::holder>) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/frontend/devicemanager.cpp:309
#19 0x00007fd4f79b8a0f in Solid::Device::listFromQuery (predicate=..., parentUdi=...) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/frontend/devicemanager.cpp:28
#20 0x00007fd4f79b91be in Solid::Device::listFromQuery (predicate=..., parentUdi=...) at /home/kaiuwe/Projekte/kf5/solid/src/solid/devices/frontend/devicemanager.cpp:86
#21 0x00007fd4fccb5e96 in TrashImpl::scanTrashDirectories (this=this@entry=0x7ffe38b46de8) at ./src/ioslaves/trash/trashimpl.cpp:1053
#22 0x00007fd4fccb90e0 in TrashImpl::list (this=this@entry=0x7ffe38b46de8) at ./src/ioslaves/trash/trashimpl.cpp:688
#23 0x00007fd4fccadad4 in TrashProtocol::listRoot (this=this@entry=0x7ffe38b46db0) at ./src/ioslaves/trash/kio_trash.cpp:533
#24 0x00007fd4fccae920 in TrashProtocol::listRoot (this=0x7ffe38b46db0) at /usr/include/x86_64-linux-gnu/qt5/QtCore/qstring.h:1311
#25 TrashProtocol::listDir (this=0x7ffe38b46db0, url=...) at ./src/ioslaves/trash/kio_trash.cpp:417
#26 0x00007fd4fcb885ce in KIO::SlaveBase::dispatch (this=0x7ffe38b46dc0, command=71, data=...) at ./src/core/slavebase.cpp:1301
#27 0x00007fd4fcb89096 in KIO::SlaveBase::dispatchLoop (this=0x7ffe38b46dc0) at ./src/core/slavebase.cpp:339
#28 0x00007fd4fccb00d7 in kdemain (argc=<optimized out>, argv=0x7ffe38b46f20) at ./src/ioslaves/trash/kio_trash.cpp:47
#29 0x000055845985a4fa in main (argc=5, argv=0x7ffe38b47098) at ./src/kioslave/kioslave.cpp:152

Not sure how this particular crash really comes to be. It would mean the manager is destroyed during its constructor or something? Dunno. Still, I found that it is called from separate threads... It's not documented as such as far as I can tell, maybe it's also a side-effect of having multiple idevice callbacks registered e.g. by the AFC KIO and others.

@ahmadsamir @sitter @fvogt

Edited by Kai Uwe Broulik

Merge request reports