| 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/Implemented 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
|