Qt/curl: fix segfault in curl

The QThread lived longer than the m_curl object.
This lead to a crash when closing RPCS3 while the download is still in progress.
This commit is contained in:
Megamouse 2021-01-12 23:57:26 +01:00 committed by Ivan
parent 8eaf76394c
commit cfe660ab35
2 changed files with 28 additions and 7 deletions

View file

@ -19,13 +19,31 @@ usz curl_write_cb_compat(char* ptr, usz /*size*/, usz nmemb, void* userdata)
downloader::downloader(QWidget* parent)
: QObject(parent)
, m_parent(parent)
, m_curl(new curl_handle(this))
{
m_curl = new curl_handle(this);
connect(this, &downloader::signal_buffer_update, this, &downloader::handle_buffer_update);
}
downloader::~downloader()
{
m_curl_abort = true;
if (m_thread && m_thread->isRunning())
{
m_thread->wait();
}
}
void downloader::start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title, bool keep_progress_dialog_open, int exptected_size)
{
connect(this, &downloader::signal_buffer_update, this, &downloader::handle_buffer_update);
if (m_thread)
{
m_curl_abort = true;
if (m_thread->isRunning())
{
m_thread->wait();
}
m_thread->deleteLater();
}
m_keep_progress_dialog_open = keep_progress_dialog_open;
m_curl_buf.clear();
@ -36,7 +54,7 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p
curl_easy_setopt(m_curl->get_curl(), CURLOPT_WRITEDATA, this);
curl_easy_setopt(m_curl->get_curl(), CURLOPT_FOLLOWLOCATION, follow_location ? 1 : 0);
const auto thread = QThread::create([this]
m_thread = QThread::create([this]
{
const auto result = curl_easy_perform(m_curl->get_curl());
m_curl_success = result == CURLE_OK;
@ -49,7 +67,7 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p
}
});
connect(thread, &QThread::finished, this, [this]()
connect(m_thread, &QThread::finished, this, [this]()
{
if (m_curl_abort)
{
@ -95,8 +113,8 @@ void downloader::start(const std::string& url, bool follow_location, bool show_p
}
}
thread->setObjectName("Compat Update");
thread->start();
m_thread->setObjectName("Download Thread");
m_thread->start();
}
void downloader::update_progress_dialog(const QString& title)

View file

@ -11,7 +11,8 @@ class downloader : public QObject
Q_OBJECT
public:
downloader(QWidget* parent = nullptr);
explicit downloader(QWidget* parent = nullptr);
~downloader();
void start(const std::string& url, bool follow_location, bool show_progress_dialog, const QString& progress_dialog_title = "", bool keep_progress_dialog_open = false, int expected_size = -1);
usz update_buffer(char* data, usz size);
@ -43,4 +44,6 @@ private:
progress_dialog* m_progress_dialog = nullptr;
atomic_t<bool> m_keep_progress_dialog_open = false;
QString m_progress_dialog_title;
QThread* m_thread = nullptr;
};