Fixed a libcurl memory leak in the scraper.

This commit is contained in:
Leon Styhre 2020-10-18 11:01:56 +02:00
parent da37e2c11a
commit 923d1df479
5 changed files with 28 additions and 22 deletions

View file

@ -43,7 +43,8 @@ GuiScraperSearch::GuiScraperSearch(
mBusyAnim(window),
mSearchType(type),
mScrapeCount(scrapeCount),
mScrapeRatings(false)
mScrapeRatings(false),
mFoundGame(false)
{
addChild(&mGrid);
@ -124,6 +125,11 @@ GuiScraperSearch::GuiScraperSearch(
updateViewStyle();
}
GuiScraperSearch::~GuiScraperSearch()
{
HttpReq::cleanupCurlMulti();
}
void GuiScraperSearch::onSizeChanged()
{
mGrid.setSize(mSize);

View file

@ -38,6 +38,7 @@ public:
};
GuiScraperSearch(Window* window, SearchType searchType, unsigned int scrapeCount = 1);
~GuiScraperSearch();
void search(const ScraperSearchParams& params);
void openInputScreen(ScraperSearchParams& from);

View file

@ -149,7 +149,7 @@ protected:
friend std::unique_ptr<ScraperSearchHandle>
startMediaURLsFetch(const std::string& gameIDs);
std::queue< std::unique_ptr<ScraperRequest> > mRequestQueue;
std::queue<std::unique_ptr<ScraperRequest>> mRequestQueue;
std::vector<ScraperSearchResult> mResults;
};

View file

@ -16,8 +16,7 @@
#include <assert.h>
CURLM* HttpReq::s_multi_handle = curl_multi_init();
CURLM* HttpReq::s_multi_handle;
std::map<CURL*, HttpReq*> HttpReq::s_requests;
std::string HttpReq::urlEncode(const std::string &s)
@ -26,7 +25,7 @@ std::string HttpReq::urlEncode(const std::string &s)
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.~";
std::string escaped="";
for (size_t i=0; i<s.length(); i++) {
for (size_t i = 0; i < s.length(); i++) {
if (unreserved.find_first_of(s[i]) != std::string::npos) {
escaped.push_back(s[i]);
}
@ -50,6 +49,12 @@ bool HttpReq::isUrl(const std::string& str)
HttpReq::HttpReq(const std::string& url) : mStatus(REQ_IN_PROGRESS), mHandle(nullptr)
{
// The multi-handle is cleaned up via a call from GuiScraperSearch after the scraping
// has been completed for a game, meaning the handle is valid for all cURL requests
// performed for the current game.
if (!s_multi_handle)
s_multi_handle = curl_multi_init();
mHandle = curl_easy_init();
// On Windows, use the bundled cURL TLS/SSL certificates (which actually come from the
@ -200,14 +205,8 @@ std::string HttpReq::getErrorMsg()
// Return value is number of elements successfully read.
size_t HttpReq::write_content(void* buff, size_t size, size_t nmemb, void* req_ptr)
{
std::stringstream& ss = ((HttpReq*)req_ptr)->mContent;
ss.write((char*)buff, size * nmemb);
std::stringstream& ss = (static_cast<HttpReq*>(req_ptr))->mContent;
ss.write(static_cast<char*>(buff), size * nmemb);
return nmemb;
}
// Used as a curl callback.
//int HttpReq::update_progress(void* req_ptr, double dlTotal,
// double dlNow, double ulTotal, double ulNow)
//{
//}

View file

@ -40,31 +40,34 @@ class HttpReq
{
public:
HttpReq(const std::string& url);
~HttpReq();
enum Status {
REQ_IN_PROGRESS, // Request is in progress.
REQ_SUCCESS, // Request completed successfully, get it with getContent().
REQ_IO_ERROR, // Some error happened, get it with getErrorMsg().
REQ_BAD_STATUS_CODE, // Some invalid HTTP response status code happened (non-200).
REQ_INVALID_RESPONSE // The HTTP response was invalid.
};
Status status(); // Process any received data and return the status afterwards.
std::string getErrorMsg();
std::string getContent() const; // mStatus must be REQ_SUCCESS.
static std::string urlEncode(const std::string &s);
static bool isUrl(const std::string& s);
static void cleanupCurlMulti()
{
if (s_multi_handle != nullptr) {
curl_multi_cleanup(s_multi_handle);
s_multi_handle = nullptr;
}
};
private:
static size_t write_content(void* buff, size_t size, size_t nmemb, void* req_ptr);
//static int update_progress(void* req_ptr, double dlTotal, double dlNow,
// double ulTotal, double ulNow);
void onError(const char* msg);
// God dammit libcurl why can't you have some way to check the status of an
// individual handle why do I have to handle ALL messages at once.
@ -72,10 +75,7 @@ private:
static CURLM* s_multi_handle;
void onError(const char* msg);
CURL* mHandle;
Status mStatus;
std::stringstream mContent;