Summary: | Segfault in ProjectFileDataProvider::projectOpened()'s nested event loop when exiting KDevelop right after a large project is opened | ||
---|---|---|---|
Product: | [Applications] kdevelop | Reporter: | Igor Kushnir <igorkuo> |
Component: | UI: QuickOpen | Assignee: | Igor Kushnir <igorkuo> |
Status: | RESOLVED FIXED | ||
Severity: | crash | ||
Priority: | NOR | ||
Version First Reported In: | git master | ||
Target Milestone: | --- | ||
Platform: | Compiled Sources | ||
OS: | Linux | ||
Latest Commit: | https://invent.kde.org/kdevelop/kdevelop/commit/3f1b6392cb528d7b8986ab9a0a641cd9e346ef8d | Version Fixed In: | 5.7.0 |
Sentry Crash Report: |
Description
Igor Kushnir
2020-10-06 09:08:46 UTC
Git commit 3f1b6392cb528d7b8986ab9a0a641cd9e346ef8d by Igor Kushnir. Committed on 13/02/2021 at 08:36. Pushed by igorkushnir into branch 'master'. Don't process events in ProjectFileDataProvider::projectOpened() When a user exits KDevelop or closes the just opened project in the ProjectFileDataProvider::projectOpened()'s nested event loop, IProjectController::projectClosing() signal is emitted before some slots connected to IProjectController::projectOpened() signal ale invoked (more precisely, the slots that were connected to projectOpened() signal later than the ProjectFileDataProvider::projectOpened() slot). Thus a valid assumption that a slot connected to projectOpened() is always called before a slot connected to projectClosing() becomes incorrect and causes a crash, e.g. a segmentation fault in ClassModel::removeProjectNode(). In addition, ProjectController::projectImportingFinished() calls reparseProject() after emitting the projectOpened() signal. Delaying this call until after the project is closed and possibly destroyed would likely case a crash or some other bug. Queuing the slow code and its associated QApplication::processEvents() instead of calling it directly in ProjectFileDataProvider::projectOpened() would not eliminate the crash, but move the segmentation fault from an unrelated class to ProjectFileDataProvider::fileAddedToSet(). When the user disables the Quick Open plugin in this projectOpened()'s nested event loop, a similar crash occurs. These crashes could be fixed by checking whether the project is still open and checking QPointer{this} after the call to QApplication::processEvents(). But the code wouldn't become crash-proof even then. ProjectFileDataProvider should not enter a nested event loop while iterating over the project tree, because a project item can be destroyed during the event loop when a user removes a file, which can make one of the pointers to ProjectBaseItem held by KDevelop::forEachFile() dangling. The benefits of eliminating the nested event loop: 1) no need for verbose crash workarounds; 2) opening projects can be optimized by sorting and merging sorted ranges. In particular, a performance pitfall, when multiple large projects are opened in a certain order, can be eliminated. Related: bug 427379 FIXED-IN: 5.7.0 M +0 -8 plugins/quickopen/projectfilequickopen.cpp https://invent.kde.org/kdevelop/kdevelop/commit/3f1b6392cb528d7b8986ab9a0a641cd9e346ef8d |