Summary: | Crash on exit: Called object is not of the correct type | ||
---|---|---|---|
Product: | [Applications] kdepim | Reporter: | Louis Moureaux <m_louis30> |
Component: | libkdepim | Assignee: | kdepim bugs <kdepim-bugs> |
Status: | RESOLVED FIXED | ||
Severity: | crash | CC: | faure |
Priority: | NOR | ||
Version First Reported In: | 6.2.1 | ||
Target Milestone: | --- | ||
Platform: | Neon | ||
OS: | Linux | ||
Latest Commit: | https://invent.kde.org/pim/libkdepim/-/commit/e7435bc6d80b5a9c170d209928586c5295e646b1 | Version Fixed In: | |
Sentry Crash Report: |
Description
Louis Moureaux
2024-08-15 22:18:52 UTC
Still present in 6.2.1. Steps to reproduce: 1. Start Kontact (kmail view) 2. Run "akonadictl restart" from the shell 3. Quit Kontact 4. Kontact aborts I narrowed this crash down to a bug in KPIM::ProgressDialog: 1. ProgressDialog has a child TransactionItemView object 2. In ProgressDialog::slotTransactionCompleted(), a TransactionItem's destroyed() signal is connected to TransactionItemView::slotLayoutFirstItem on the view 3. The view owns the item (recursively through multiple objects) 4. When the view is deleted, the view's destructor runs first 5. At this point the object is no longer a valid TransactionItemView 6. The QObject destructor runs and deletes children 7. The TransactionItem gets deleted 8. TransactionItem emits its destroyed() signal 9. TransactionItemView::slotLayoutFirstItem gets called on the now-deleted view 10. Qt asserts I'm not sure how to fix. This might have worked only by chance in the past (if Qt wouldn't detect it it would be UB). Great analysis. As for a possible fix: TransactionItem could emit an itemDestroyed() signal (to be added), so that the code connected to that sees a full TransactionItem instance rather than a partially deleted QObject. Oh, you said TransactionItemView itself is down to a QObject. Then it needs to disconnect() the connect to the destroyed signal. This is likely a regression coming from the port from SIGNAL()/SLOT() to &Class::slot syntax. The latter syntax creates this kind of bug because the connection remains valid until full destruction, while the SIGNAL/SLOT solution was based on virtual methods so no slot was called in a partially destroyed receiver. This means storing the return value of the connect() statement into a QMetaObject::Connection member variable, and using it to disconnect in the destructor. A possibly relevant merge request was started @ https://invent.kde.org/pim/libkdepim/-/merge_requests/27 Git commit 15099be5c7b1ca365600f2a3d7550bac0bde0e1a by David Faure. Committed on 24/12/2024 at 16:18. Pushed by dfaure into branch 'master'. Fix crash on exit if mailcheck is happening Disconnect to avoid calling into a partially-deleted TransactionItemView Downside: these connections accumulate over time... M +12 -2 src/progresswidget/progressdialog.cpp M +1 -0 src/progresswidget/progressdialog.h https://invent.kde.org/pim/libkdepim/-/commit/15099be5c7b1ca365600f2a3d7550bac0bde0e1a Git commit e7435bc6d80b5a9c170d209928586c5295e646b1 by David Faure. Committed on 26/12/2024 at 12:22. Pushed by dfaure into branch 'release/24.12'. Fix crash on exit if mailcheck is happening Disconnect to avoid calling into a partially-deleted TransactionItemView Downside: these connections accumulate over time... M +12 -2 src/progresswidget/progressdialog.cpp M +1 -0 src/progresswidget/progressdialog.h https://invent.kde.org/pim/libkdepim/-/commit/e7435bc6d80b5a9c170d209928586c5295e646b1 |