Fixed segfault error when cleaning up libcurl
This commit is contained in:
parent
916e415331
commit
0c9b835919
2 changed files with 21 additions and 34 deletions
|
|
@ -8,7 +8,7 @@
|
|||
std::mutex FileDownloader::newDownloadsMutex;
|
||||
std::vector<FileDownloader::DownloadHandler> FileDownloader::newDownloads;
|
||||
std::atomic<bool> FileDownloader::shutdownThread;
|
||||
FileDownloader::MultiHandle FileDownloader::mHandle;
|
||||
CURLM* FileDownloader::mHandle;
|
||||
std::vector<FileDownloader::DownloadHandler> FileDownloader::currentDownloads;
|
||||
std::unique_ptr<std::thread> FileDownloader::downloadThread;
|
||||
|
||||
|
|
@ -22,10 +22,11 @@ std::shared_ptr<FileDownloader::DownloadData> FileDownloader::download_data_from
|
|||
auto downloadData = std::make_shared<DownloadData>();
|
||||
h.data = downloadData;
|
||||
h.data->status = DownloadData::Status::IN_PROGRESS;
|
||||
h.eHandle = create_easy_handle();
|
||||
curl_easy_setopt(h.eHandle.get(), CURLOPT_URL, url.data());
|
||||
disable_ssl_verification(h.eHandle.get());
|
||||
save_to_string(h.eHandle.get(), &h.data->str);
|
||||
h.eHandle = curl_easy_init();
|
||||
curl_easy_setopt(h.eHandle, CURLOPT_URL, url.data());
|
||||
curl_easy_setopt(h.eHandle, CURLOPT_NOSIGNAL, 1);
|
||||
disable_ssl_verification(h.eHandle);
|
||||
save_to_string(h.eHandle, &h.data->str);
|
||||
|
||||
{
|
||||
std::scoped_lock newDownloadsLock(newDownloadsMutex);
|
||||
|
|
@ -41,7 +42,7 @@ std::shared_ptr<FileDownloader::DownloadData> FileDownloader::download_data_from
|
|||
void FileDownloader::add_new_handlers_to_multi() {
|
||||
std::scoped_lock newDownloadsLock(newDownloadsMutex);
|
||||
for(auto& handler : newDownloads) {
|
||||
curl_multi_add_handle(mHandle.get(), handler.eHandle.get());
|
||||
curl_multi_add_handle(mHandle, handler.eHandle);
|
||||
currentDownloads.emplace_back(std::move(handler));
|
||||
}
|
||||
newDownloads.clear();
|
||||
|
|
@ -50,7 +51,7 @@ void FileDownloader::add_new_handlers_to_multi() {
|
|||
void FileDownloader::download_thread_update() {
|
||||
int stillRunning = 0;
|
||||
|
||||
mHandle = create_multi_handle();
|
||||
mHandle = curl_multi_init();
|
||||
add_new_handlers_to_multi();
|
||||
|
||||
do {
|
||||
|
|
@ -60,36 +61,42 @@ void FileDownloader::download_thread_update() {
|
|||
CURLMcode mc;
|
||||
int numfds;
|
||||
|
||||
mc = curl_multi_perform(mHandle.get(), &stillRunning);
|
||||
mc = curl_multi_perform(mHandle, &stillRunning);
|
||||
|
||||
for(;;) {
|
||||
int msgCount;
|
||||
CURLMsg* eHandleMsg = curl_multi_info_read(mHandle.get(), &msgCount);
|
||||
CURLMsg* eHandleMsg = curl_multi_info_read(mHandle, &msgCount);
|
||||
if(!eHandleMsg)
|
||||
break;
|
||||
if(eHandleMsg->msg == CURLMSG_DONE) {
|
||||
auto it = std::find_if(currentDownloads.begin(), currentDownloads.end(), [eHandleMsg](auto& d) {
|
||||
return eHandleMsg->easy_handle == d.eHandle.get();
|
||||
return eHandleMsg->easy_handle == d.eHandle;
|
||||
});
|
||||
if(it != currentDownloads.end()) {
|
||||
DownloadHandler& download = *it;
|
||||
download.data->status = eHandleMsg->data.result == CURLE_OK ? DownloadData::Status::SUCCESS : DownloadData::Status::FAILURE;
|
||||
curl_multi_remove_handle(mHandle, download.eHandle);
|
||||
curl_easy_cleanup(download.eHandle);
|
||||
currentDownloads.erase(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(mc == CURLM_OK)
|
||||
curl_multi_poll(mHandle.get(), nullptr, 0, 1000, &numfds);
|
||||
curl_multi_poll(mHandle, nullptr, 0, 1000, &numfds);
|
||||
else {
|
||||
std::cout << "curl_multi failed" << std::endl;
|
||||
break;
|
||||
}
|
||||
} while(stillRunning);
|
||||
|
||||
for(auto& download : currentDownloads)
|
||||
for(auto& download : currentDownloads) {
|
||||
download.data->status = DownloadData::Status::FAILURE;
|
||||
curl_multi_remove_handle(mHandle, download.eHandle);
|
||||
curl_easy_cleanup(download.eHandle);
|
||||
}
|
||||
currentDownloads.clear();
|
||||
curl_multi_cleanup(mHandle);
|
||||
}
|
||||
|
||||
void FileDownloader::save_to_string(CURL* curl, std::string* str) {
|
||||
|
|
@ -102,20 +109,6 @@ void FileDownloader::disable_ssl_verification(CURL* curl) {
|
|||
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
}
|
||||
|
||||
FileDownloader::EasyHandle FileDownloader::create_easy_handle() {
|
||||
auto easyHandle = EasyHandle(curl_easy_init(), curl_easy_cleanup);
|
||||
if(!easyHandle)
|
||||
throw std::runtime_error("[FileDownloader::create_easy_handle] Failed to create CURL easy handle");
|
||||
return easyHandle;
|
||||
}
|
||||
|
||||
FileDownloader::MultiHandle FileDownloader::create_multi_handle() {
|
||||
auto multiHandle = EasyHandle(curl_multi_init(), curl_multi_cleanup);
|
||||
if(!multiHandle)
|
||||
throw std::runtime_error("[FileDownloader::create_multi_handle] Failed to create CURL multi handle");
|
||||
return multiHandle;
|
||||
}
|
||||
|
||||
size_t FileDownloader::write_to_string(void* contents, size_t size, size_t nmemb, void* userp) {
|
||||
size_t realsize = size * nmemb;
|
||||
auto str = reinterpret_cast<std::string*>(userp);
|
||||
|
|
|
|||
|
|
@ -24,21 +24,18 @@ class FileDownloader {
|
|||
static std::shared_ptr<DownloadData> download_data_from_url(std::string_view url);
|
||||
static void cleanup();
|
||||
private:
|
||||
typedef std::unique_ptr<CURL, std::function<void(CURL*)>> EasyHandle;
|
||||
typedef std::unique_ptr<CURLM, std::function<void(CURLM*)>> MultiHandle;
|
||||
|
||||
static void add_new_handlers_to_multi();
|
||||
static void download_thread_update();
|
||||
|
||||
struct DownloadHandler {
|
||||
EasyHandle eHandle;
|
||||
CURL* eHandle;
|
||||
std::shared_ptr<DownloadData> data;
|
||||
};
|
||||
|
||||
static std::mutex newDownloadsMutex;
|
||||
static std::vector<DownloadHandler> newDownloads;
|
||||
static std::atomic<bool> shutdownThread;
|
||||
static MultiHandle mHandle;
|
||||
static CURLM* mHandle;
|
||||
static std::vector<DownloadHandler> currentDownloads;
|
||||
static std::unique_ptr<std::thread> downloadThread;
|
||||
|
||||
|
|
@ -48,9 +45,6 @@ class FileDownloader {
|
|||
static timeval get_timeout(CURLM* mCurl);
|
||||
static int wait_if_needed(CURLM* mCurl, timeval& timeout);
|
||||
|
||||
static EasyHandle create_easy_handle();
|
||||
static MultiHandle create_multi_handle();
|
||||
|
||||
static size_t write_to_string(void* contents, size_t size, size_t nmemb, void* userp);
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue