hallas added a comment.
In D19170#416067 <https://phabricator.kde.org/D19170#416067>, @hallas wrote: > In D19170#415760 <https://phabricator.kde.org/D19170#415760>, @dfaure wrote: > > > If some code is deleting this job from a slot connected to it, that code needs to be fixed. This hack isn't a fix, it will only create more problems.. > > > > E.g. if some other bad code runs the event loop in the slot connected to finished, it will now delete the job, and we'll get the exact same crash but on `if (emitResult)` this time. > > > > This is a big no from me. The emitter of a signal MUST NOT be deleted in slots connected to it. > > > > The bug needs proper analysis. > > > Hi David, > > thanks for the reply :) I completely agree with you that this is a hack and shouldn't go in, it was merely meant as an aid in doing proper analysis of the bug. I hope one of the people who can actually reproduce the problem can try with this patch enabled and see if it goes away. If it does then I think we can be pretty certain that someone is deleting jobs that they shouldn't. Otherwise I don't have much to go on. I have tried to reproduce the problem in various ways, copying to/from an NTFS drive and also copying to/from SMB but I can't get it to crash. I have been looking some more into the code and I still cannot figure out how the KJob instance can get invalidated. Have you looked at the backtraces? Do you have any ideas or pointers to where to look? > > Appreciate the feedback Ok, I think I just found a way to reproduce the problem: - Move a directory with a bunch of files to a NTFS USB Drive - While it is moving the files, move them back - Sometimes I have to have more then one move back and forth running for it to crash I have now built KIO with address sanitizer and I get the following info: ==7539==ERROR: AddressSanitizer: heap-use-after-free on address 0x6120002e3de0 at pc 0x7f2cdbbed173 bp 0x7ffec26c5050 sp 0x7ffec26c5040 READ of size 8 at 0x6120002e3de0 thread T0 #0 0x7f2cdbbed172 in KIO::CopyJobPrivate::slotResultErrorCopyingFiles(KJob*) ../src/core/copyjob.cpp:1464 #1 0x7f2cdbbeb26f in KIO::CopyJobPrivate::slotResultCopyingFiles(KJob*) ../src/core/copyjob.cpp:1333 #2 0x7f2cdbbfba35 in KIO::CopyJob::slotResult(KJob*) ../src/core/copyjob.cpp:2160 #3 0x7f2cd612a986 in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x264986) #4 0x7f2cd7e6e18b in KJob::result(KJob*, KJob::QPrivateSignal) (/usr/lib64/libKF5CoreAddons.so.5+0x3d18b) #5 0x7f2cd7e6ecc0 in KJob::finishJob(bool) (/usr/lib64/libKF5CoreAddons.so.5+0x3dcc0) #6 0x7f2cdbc95d8b in KIO::FileCopyJob::slotResult(KJob*) ../src/core/filecopyjob.cpp:497 #7 0x7f2cd612a986 in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x264986) #8 0x7f2cd7e6e18b in KJob::result(KJob*, KJob::QPrivateSignal) (/usr/lib64/libKF5CoreAddons.so.5+0x3d18b) #9 0x7f2cd7e6ecc0 in KJob::finishJob(bool) (/usr/lib64/libKF5CoreAddons.so.5+0x3dcc0) #10 0x7f2cdbcb2267 in KIO::SimpleJob::slotFinished() ../src/core/simplejob.cpp:232 #11 0x7f2cdbcb265d in KIO::SimpleJob::slotError(int, QString const&) ../src/core/simplejob.cpp:245 #12 0x7f2cdbcb8e49 in QtPrivate::FunctorCall<QtPrivate::IndexesList<0, 1>, QtPrivate::List<int, QString const&>, void, void (KIO::SimpleJob::*)(int, QString const&)>::call(void (KIO::SimpleJob::*)(int, QString const&), KIO::SimpleJob*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:134 #13 0x7f2cdbcb88ea in void QtPrivate::FunctionPointer<void (KIO::SimpleJob::*)(int, QString const&)>::call<QtPrivate::List<int, QString const&>, void>(void (KIO::SimpleJob::*)(int, QString const&), KIO::SimpleJob*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:167 #14 0x7f2cdbcb83a7 in QtPrivate::QSlotObject<void (KIO::SimpleJob::*)(int, QString const&), QtPrivate::List<int, QString const&>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobjectdefs_impl.h:396 #15 0x7f2cd612a986 in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x264986) #16 0x7f2cdbc63a91 in KIO::SlaveInterface::error(int, QString const&) src/core/KF5KIOCore_autogen/include/moc_slaveinterface.cpp:425 #17 0x7f2cdbc5da14 in KIO::SlaveInterface::dispatch(int, QByteArray const&) ../src/core/slaveinterface.cpp:192 #18 0x7f2cdbc5cac7 in KIO::SlaveInterface::dispatch() ../src/core/slaveinterface.cpp:89 #19 0x7f2cdbc69a74 in KIO::Slave::gotInput() ../src/core/slave.cpp:406 #20 0x7f2cdbc71d88 in QtPrivate::FunctorCall<QtPrivate::IndexesList<>, QtPrivate::List<>, void, void (KIO::Slave::*)()>::call(void (KIO::Slave::*)(), KIO::Slave*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:134 #21 0x7f2cdbc719cb in void QtPrivate::FunctionPointer<void (KIO::Slave::*)()>::call<QtPrivate::List<>, void>(void (KIO::Slave::*)(), KIO::Slave*, void**) /usr/include/qt5/QtCore/qobjectdefs_impl.h:167 #22 0x7f2cdbc7118b in QtPrivate::QSlotObject<void (KIO::Slave::*)(), QtPrivate::List<>, void>::impl(int, QtPrivate::QSlotObjectBase*, QObject*, void**, bool*) /usr/include/qt5/QtCore/qobjectdefs_impl.h:396 #23 0x7f2cd612a986 in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x264986) #24 0x7f2cdbb5fdaa in KIO::Connection::readyRead() src/core/KF5KIOCore_autogen/include/moc_connection_p.cpp:143 #25 0x7f2cdbb5c1a0 in KIO::ConnectionPrivate::dequeue() ../src/core/connection.cpp:46 #26 0x7f2cdbb5f9ae in KIO::Connection::qt_static_metacall(QObject*, QMetaObject::Call, int, void**) src/core/KF5KIOCore_autogen/include/moc_connection_p.cpp:87 #27 0x7f2cd612b5a9 in QObject::event(QEvent*) (/usr/lib64/libQt5Core.so.5+0x2655a9) #28 0x7f2cd727ad8b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x15ad8b) #29 0x7f2cd728234e in QApplication::notify(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x16234e) #30 0x7f2cd6101366 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (/usr/lib64/libQt5Core.so.5+0x23b366) #31 0x7f2cd61041c0 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (/usr/lib64/libQt5Core.so.5+0x23e1c0) #32 0x7f2cd6154362 (/usr/lib64/libQt5Core.so.5+0x28e362) #33 0x7f2ccfecfe26 in g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0+0x4be26) #34 0x7f2ccfed005f (/usr/lib64/libglib-2.0.so.0+0x4c05f) #35 0x7f2ccfed00eb in g_main_context_iteration (/usr/lib64/libglib-2.0.so.0+0x4c0eb) #36 0x7f2cd615414e in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (/usr/lib64/libQt5Core.so.5+0x28e14e) #37 0x7f2cc57ad740 (/usr/lib64/libQt5XcbQpa.so.5+0xcc740) #38 0x7f2cd6100159 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (/usr/lib64/libQt5Core.so.5+0x23a159) #39 0x7f2cd7469cc6 in QDialog::exec() (/usr/lib64/libQt5Widgets.so.5+0x349cc6) #40 0x7f2cd9300ed8 in KMessageBox::createKMessageBox(QDialog*, QDialogButtonBox*, QIcon const&, QString const&, QStringList const&, QString const&, bool*, QFlags<KMessageBox::Option>, QString const&, QMessageBox::Icon) (/usr/lib64/libKF5WidgetsAddons.so.5+0xbeed8) #41 0x7f2cd930108d in KMessageBox::createKMessageBox(QDialog*, QDialogButtonBox*, QMessageBox::Icon, QString const&, QStringList const&, QString const&, bool*, QFlags<KMessageBox::Option>, QString const&) (/usr/lib64/libKF5WidgetsAddons.so.5+0xbf08d) #42 0x7f2cd9304a79 (/usr/lib64/libKF5WidgetsAddons.so.5+0xc2a79) #43 0x7f2cd9304f5e (/usr/lib64/libKF5WidgetsAddons.so.5+0xc2f5e) #44 0x7f2cdc3978ec (/usr/lib64/libKF5JobWidgets.so.5+0xd8ec) #45 0x7f2cd612b5a9 in QObject::event(QEvent*) (/usr/lib64/libQt5Core.so.5+0x2655a9) #46 0x7f2cd727ad8b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x15ad8b) #47 0x7f2cd728234e in QApplication::notify(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x16234e) #48 0x7f2cd6101366 in QCoreApplication::notifyInternal2(QObject*, QEvent*) (/usr/lib64/libQt5Core.so.5+0x23b366) #49 0x7f2cd61041c0 in QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) (/usr/lib64/libQt5Core.so.5+0x23e1c0) #50 0x7f2cd6154362 (/usr/lib64/libQt5Core.so.5+0x28e362) #51 0x7f2ccfecfe26 in g_main_context_dispatch (/usr/lib64/libglib-2.0.so.0+0x4be26) #52 0x7f2ccfed005f (/usr/lib64/libglib-2.0.so.0+0x4c05f) #53 0x7f2ccfed00eb in g_main_context_iteration (/usr/lib64/libglib-2.0.so.0+0x4c0eb) #54 0x7f2cd615414e in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) (/usr/lib64/libQt5Core.so.5+0x28e14e) #55 0x7f2cc57ad740 (/usr/lib64/libQt5XcbQpa.so.5+0xcc740) #56 0x7f2cd6100159 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) (/usr/lib64/libQt5Core.so.5+0x23a159) #57 0x7f2cd6108b3f in QCoreApplication::exec() (/usr/lib64/libQt5Core.so.5+0x242b3f) #58 0x7f2cdf3aa336 in kdemain ../src/main.cpp:168 #59 0x5614d66ce86b in main src/dolphin_dummy.cpp:3 #60 0x7f2cde617ae6 in __libc_start_main (/lib64/libc.so.6+0x21ae6) #61 0x5614d66ce749 in _start (/home/dha/workspace/kde/install/bin/dolphin+0x749) 0x6120002e3de0 is located 288 bytes inside of 320-byte region [0x6120002e3cc0,0x6120002e3e00) freed by thread T0 here: #0 0x7f2cdf7774b0 in operator delete(void*) (/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libasan.so+0xe14b0) #1 0x7f2cdbc0912b in KIO::CopyJobPrivate::~CopyJobPrivate() ../src/core/copyjob.cpp:120 #2 0x7f2cdbc8633d in KIO::Job::~Job() ../src/core/job.cpp:55 #3 0x7f2cdbbd7638 in KIO::CopyJob::~CopyJob() ../src/core/copyjob.cpp:304 #4 0x7f2cdbbd7653 in KIO::CopyJob::~CopyJob() ../src/core/copyjob.cpp:306 #5 0x7f2cd612b5c7 in QObject::event(QEvent*) (/usr/lib64/libQt5Core.so.5+0x2655c7) #6 0x7f2cd727ad8b in QApplicationPrivate::notify_helper(QObject*, QEvent*) (/usr/lib64/libQt5Widgets.so.5+0x15ad8b) previously allocated by thread T0 here: #0 0x7f2cdf776638 in operator new(unsigned long) (/usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/libasan.so+0xe0638) #1 0x7f2cdbc04c0b in KIO::CopyJobPrivate::newJob(QList<QUrl> const&, QUrl const&, KIO::CopyJob::CopyMode, bool, QFlags<KIO::JobFlag>) (/home/dha/workspace/kde/install/lib64/libKF5KIOCore.so.5+0x151c0b) #2 0x7f2cdbbfd8d3 in KIO::move(QList<QUrl> const&, QUrl const&, QFlags<KIO::JobFlag>) ../src/core/copyjob.cpp:2252 #3 0x7f2cdc818bc4 in KIO::DropJobPrivate::doCopyToDirectory() ../src/widgets/dropjob.cpp:486 #4 0x7f2cdc817e44 in KIO::DropJobPrivate::slotTriggered(QAction*) ../src/widgets/dropjob.cpp:431 #5 0x7f2cdc8180b8 in operator() ../src/widgets/dropjob.cpp:464 #6 0x7f2cdc81c95e in call /usr/include/qt5/QtCore/qobjectdefs_impl.h:128 #7 0x7f2cdc81c68e in call<QtPrivate::List<QAction*>, void> /usr/include/qt5/QtCore/qobjectdefs_impl.h:238 #8 0x7f2cdc81c41a in impl /usr/include/qt5/QtCore/qobjectdefs_impl.h:421 #9 0x7f2cd612a986 in QMetaObject::activate(QObject*, int, int, void**) (/usr/lib64/libQt5Core.so.5+0x264986) #10 0x7f2cd73e8b01 in QMenu::triggered(QAction*) (/usr/lib64/libQt5Widgets.so.5+0x2c8b01) SUMMARY: AddressSanitizer: heap-use-after-free ../src/core/copyjob.cpp:1464 in KIO::CopyJobPrivate::slotResultErrorCopyingFiles(KJob*) Shadow bytes around the buggy address: 0x0c2480054760: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c2480054770: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c2480054780: fd fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa 0x0c2480054790: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c24800547a0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd =>0x0c24800547b0: fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd fd fd 0x0c24800547c0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c24800547d0: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x0c24800547e0: fd fd fd fd fd fd fd fd fd fd fd fa fa fa fa fa 0x0c24800547f0: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c2480054800: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb ==7539==ABORTING I haven't figured out what's going on though. But the stack from where the object was freed looks like it was freed directly off an eventloop meaning it is most likely a result of a `deleteLater` call, but why would a slot still be connected to it? Or could it be caused by the fact that more then one `QEventLoop` is active since there is a `KMessageBox::exec` call involved? I will keep looking, but please comment if you have any pointers :) REPOSITORY R244 KCoreAddons REVISION DETAIL https://phabricator.kde.org/D19170 To: hallas, #frameworks, elvisangelaccio, dfaure Cc: dhaumann, kde-frameworks-devel, michaelh, ngraham, bruns