fix: prevent segfault due to callbacks into deleted objects
Since network requests are, for the most part, asynchronous, there's a chance a request only comes through after the request sender has already been deleted. This adds a global (read static) hash table relating models for the mod downloader to their status (true = alive, false = destroyed). It is a bit of a hack, but I couldn't come up with a better way of doing this. To reproduce the issue before this commit: scroll really quickly through CF mods, to trigger network requests for their versions and description. Then, in the middle of it close the mod downloader. Sometimes this will create a crash. Signed-off-by: flow <flowlnlnln@gmail.com>
This commit is contained in:
parent
cee41b87f7
commit
4a8abc948e
@ -13,7 +13,16 @@
|
|||||||
|
|
||||||
namespace ModPlatform {
|
namespace ModPlatform {
|
||||||
|
|
||||||
ListModel::ListModel(ModPage* parent) : QAbstractListModel(parent), m_parent(parent) {}
|
// HACK: We need this to prevent callbacks from calling the ListModel after it has already been deleted.
|
||||||
|
// This leaks a tiny bit of memory per time the user has opened the mod dialog. How to make this better?
|
||||||
|
static QHash<ListModel*, bool> s_running;
|
||||||
|
|
||||||
|
ListModel::ListModel(ModPage* parent) : QAbstractListModel(parent), m_parent(parent) { s_running.insert(this, true); }
|
||||||
|
|
||||||
|
ListModel::~ListModel()
|
||||||
|
{
|
||||||
|
s_running.find(this).value() = false;
|
||||||
|
}
|
||||||
|
|
||||||
auto ListModel::debugName() const -> QString
|
auto ListModel::debugName() const -> QString
|
||||||
{
|
{
|
||||||
@ -101,7 +110,11 @@ void ListModel::requestModVersions(ModPlatform::IndexedPack const& current, QMod
|
|||||||
auto profile = (dynamic_cast<MinecraftInstance*>((dynamic_cast<ModPage*>(parent()))->m_instance))->getPackProfile();
|
auto profile = (dynamic_cast<MinecraftInstance*>((dynamic_cast<ModPage*>(parent()))->m_instance))->getPackProfile();
|
||||||
|
|
||||||
m_parent->apiProvider()->getVersions({ current.addonId.toString(), getMineVersions(), profile->getModLoaders() },
|
m_parent->apiProvider()->getVersions({ current.addonId.toString(), getMineVersions(), profile->getModLoaders() },
|
||||||
[this, current, index](QJsonDocument& doc, QString addonId) { versionRequestSucceeded(doc, addonId, index); });
|
[this, current, index](QJsonDocument& doc, QString addonId) {
|
||||||
|
if (!s_running.constFind(this).value())
|
||||||
|
return;
|
||||||
|
versionRequestSucceeded(doc, addonId, index);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListModel::performPaginatedSearch()
|
void ListModel::performPaginatedSearch()
|
||||||
@ -114,8 +127,11 @@ void ListModel::performPaginatedSearch()
|
|||||||
|
|
||||||
void ListModel::requestModInfo(ModPlatform::IndexedPack& current, QModelIndex index)
|
void ListModel::requestModInfo(ModPlatform::IndexedPack& current, QModelIndex index)
|
||||||
{
|
{
|
||||||
m_parent->apiProvider()->getModInfo(
|
m_parent->apiProvider()->getModInfo(current, [this, index](QJsonDocument& doc, ModPlatform::IndexedPack& pack) {
|
||||||
current, [this, index](QJsonDocument& doc, ModPlatform::IndexedPack& pack) { infoRequestFinished(doc, pack, index); });
|
if (!s_running.constFind(this).value())
|
||||||
|
return;
|
||||||
|
infoRequestFinished(doc, pack, index);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListModel::refresh()
|
void ListModel::refresh()
|
||||||
|
@ -18,7 +18,7 @@ class ListModel : public QAbstractListModel {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ListModel(ModPage* parent);
|
ListModel(ModPage* parent);
|
||||||
~ListModel() override = default;
|
~ListModel() override;
|
||||||
|
|
||||||
inline auto rowCount(const QModelIndex& parent) const -> int override { return modpacks.size(); };
|
inline auto rowCount(const QModelIndex& parent) const -> int override { return modpacks.size(); };
|
||||||
inline auto columnCount(const QModelIndex& parent) const -> int override { return 1; };
|
inline auto columnCount(const QModelIndex& parent) const -> int override { return 1; };
|
||||||
|
Loading…
Reference in New Issue
Block a user