diff options
| author | isanae <14251494+isanae@users.noreply.github.com> | 2019-11-27 15:15:27 -0500 |
|---|---|---|
| committer | isanae <14251494+isanae@users.noreply.github.com> | 2019-11-27 15:15:27 -0500 |
| commit | 7f2d0e672205b85425cff488aa41ba0117abd191 (patch) | |
| tree | 2a3a29b80d7bdf868fe45cc17a1a8b82dd9fbec9 /src | |
| parent | e18afba89300979a1cabaf26a956903d737e3253 (diff) | |
fix crash when changing categories on mods when the "no categories" filter is selected
Diffstat (limited to 'src')
| -rw-r--r-- | src/modlist.cpp | 27 | ||||
| -rw-r--r-- | src/modlist.h | 1 |
2 files changed, 28 insertions, 0 deletions
diff --git a/src/modlist.cpp b/src/modlist.cpp index c5bc37e9..b7a9b0a1 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -61,6 +61,7 @@ ModList::ModList(PluginContainer *pluginContainer, QObject *parent) , m_Profile(nullptr) , m_NexusInterface(nullptr) , m_Modified(false) + , m_InNotifyChange(false) , m_FontMetrics(QFont()) , m_DropOnItems(false) , m_PluginContainer(pluginContainer) @@ -1195,6 +1196,32 @@ bool ModList::removeRows(int row, int count, const QModelIndex &parent) void ModList::notifyChange(int rowStart, int rowEnd) { + // this function can emit dataChanged(), which can eventually recurse back + // here; for example: + // + // - a filter is active in the mod list, such as "no categories" + // - mods are selected and a category is set on them + // - these mods get updated here and disappear from the list because they're + // not in "no categories" anymore + // - dataChanged() is emitted + // - it's picked up in MainWindow::modlistSelectionsChanged() because the + // selected mods are gone + // - it calls setOverwriteMarkers(), which calls notifyChange() again and + // ends up here + // - dataChanged() is emitted again + // + // at this point, MO crashes because dataChanged() is not reentrant: it's in + // the middle of modifying internal data and crashes when trying to change an + // internal vector + // + // long story short, this prevents reentrancy + if (m_InNotifyChange) { + return; + } + + m_InNotifyChange = true; + Guard g([&]{ m_InNotifyChange = false; }); + if (rowStart < 0) { m_Overwrite.clear(); m_Overwritten.clear(); diff --git a/src/modlist.h b/src/modlist.h index 5ce32f6e..631401c0 100644 --- a/src/modlist.h +++ b/src/modlist.h @@ -341,6 +341,7 @@ private: std::set<int> m_RequestIDs;
mutable bool m_Modified;
+ bool m_InNotifyChange;
QFontMetrics m_FontMetrics;
|
