commit 43454a2a4751dc2a8e290f67b0c207d877d81542
parent 58eb823e68fd607ca679febf74a5f90a40fa5c4c
Author: cfillion <cfillion@users.noreply.github.com>
Date: Tue, 7 Feb 2017 02:11:57 -0500
fix possible crash when cleaning up downloads and transactions
The variables captured by a lambda are no longer availabe once that lambda
(std::function) is destroyed. This have been happening frequently since the
improved download thread scheduling code.
https://gist.github.com/cfillion/156f6e32d508155145db1f404fbe30ad
Diffstat:
4 files changed, 16 insertions(+), 12 deletions(-)
diff --git a/src/download.cpp b/src/download.cpp
@@ -250,9 +250,7 @@ void DownloadQueue::push(Download *dl)
m_onPush(dl);
m_running.insert(dl);
- dl->setCleanupHandler([=] {
- delete dl;
-
+ dl->onFinish([=] {
m_running.erase(dl);
// call m_onDone() only after every onFinish slots ran
@@ -260,6 +258,8 @@ void DownloadQueue::push(Download *dl)
m_onDone();
});
+ dl->setCleanupHandler([=] { delete dl; });
+
auto &thread = m_pool[m_running.size() % m_pool.size()];
if(!thread)
thread = make_unique<DownloadThread>();
diff --git a/src/reapack.cpp b/src/reapack.cpp
@@ -436,17 +436,20 @@ Transaction *ReaPack::setupTransaction()
&entries, &m_config->install.promptObsolete) == IDOK;
});
- m_tx->setCleanupHandler([=] {
- delete m_tx;
- m_tx = nullptr;
-
- // refresh only once all onFinish slots were ran
- refreshBrowser();
- });
+ m_tx->setCleanupHandler(bind(&ReaPack::teardownTransaction, this));
return m_tx;
}
+void ReaPack::teardownTransaction()
+{
+ delete m_tx;
+ m_tx = nullptr;
+
+ // refresh only once the registry is close
+ refreshBrowser();
+}
+
void ReaPack::refreshManager()
{
if(m_manager)
diff --git a/src/reapack.hpp b/src/reapack.hpp
@@ -91,6 +91,7 @@ private:
void registerSelf();
void doFetchIndex(const Remote &remote, DownloadQueue *, HWND, bool stale);
IndexPtr loadIndex(const Remote &remote, HWND);
+ void teardownTransaction();
std::map<int, ActionCallback> m_actions;
diff --git a/src/transaction.cpp b/src/transaction.cpp
@@ -118,12 +118,12 @@ void Transaction::fetchIndex(const Remote &remote, const function<void()> &cb)
return;
}
- m_downloadQueue.push(dl);
-
dl->onFinish([=] {
if(saveFile(dl, Index::pathFor(dl->name())))
cb();
});
+
+ m_downloadQueue.push(dl);
}
void Transaction::install(const Version *ver, const bool pin)