From e09ccd4a8d7a91f2b5f21eaaf792974b364ca31b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20Chatelain?= Date: Wed, 9 Mar 2016 18:58:18 +0100 Subject: [PATCH] Fixes badly closed curl thread when cancelled --- Win/PublishSkfb.h | 14 ++++++-------- Win/SketchfabUploader.h | 23 ++++++++++++++++++----- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/Win/PublishSkfb.h b/Win/PublishSkfb.h index 4f9ee48a..937d1e8f 100644 --- a/Win/PublishSkfb.h +++ b/Win/PublishSkfb.h @@ -54,6 +54,7 @@ int doPublishSkfb(HINSTANCE hInst,HWND hWnd); INT_PTR CALLBACK managePublishWindow(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam); INT_PTR CALLBACK manageUploadWindow(HWND hDlg,UINT message,WPARAM wParam,LPARAM lParam); HANDLE uploadThreadHandle = NULL; +SketchfabV2Uploader* uploader; LPCWSTR stringToLpwstr(std::string input) { @@ -96,8 +97,8 @@ int doPublishSkfb(HINSTANCE hInst,HWND hWnd) DWORD WINAPI thread_func(LPVOID lpParameter) { UNREFERENCED_PARAMETER(lpParameter); - SketchfabV2Uploader uploader; - lastResponse = uploader.upload(uploadWindow, skfbPbdata.skfbApiToken, skfbPbdata.skfbFilePath, skfbPbdata.skfbName, skfbPbdata.skfbDescription, skfbPbdata.skfbTags, skfbPbdata.skfbDraft, skfbPbdata.skfbPrivate, skfbPbdata.skfbPassword); + uploader = new SketchfabV2Uploader(); + lastResponse = uploader->upload(uploadWindow, skfbPbdata.skfbApiToken, skfbPbdata.skfbFilePath, skfbPbdata.skfbName, skfbPbdata.skfbDescription, skfbPbdata.skfbTags, skfbPbdata.skfbDraft, skfbPbdata.skfbPrivate, skfbPbdata.skfbPassword); SendMessage(uploadWindow, SIGNAL_UPLOAD_FINISHED, 100, 0); return 0; } @@ -138,6 +139,7 @@ INT_PTR CALLBACK manageUploadWindow(HWND hDlg,UINT message,WPARAM wParam,LPARAM errorMessageStr.c_str(), L"Upload failed", MB_OKCANCEL | MB_ICONERROR); + delete uploader; } EndDialog(hDlg, (INT_PTR)TRUE); @@ -148,12 +150,8 @@ INT_PTR CALLBACK manageUploadWindow(HWND hDlg,UINT message,WPARAM wParam,LPARAM switch (LOWORD(wParam)) { case IDC_SKFB_UPLOAD_CANCEL: - // Terminate thread - TerminateThread(uploadThreadHandle, 1); - EndDialog(hDlg, (INT_PTR)FALSE); - MessageBox(NULL, - _T("Upload cancelled by the user"), _T("Upload interrupted"), MB_OK | MB_ICONERROR); - return (INT_PTR)FALSE; + // Ask curl to stop upload + uploader->abort(); } break; } diff --git a/Win/SketchfabUploader.h b/Win/SketchfabUploader.h index 4020f8e8..8e616c31 100644 --- a/Win/SketchfabUploader.h +++ b/Win/SketchfabUploader.h @@ -12,6 +12,7 @@ typedef std::map attributes; struct ProgressbarUpdater { CURL *curl; HWND progressBar; + bool cancel; }; // Taken from https://curl.haxx.se/libcurl/c/progressfunc.html @@ -22,11 +23,12 @@ int progress_callback(void *clientp, UNREFERENCED_PARAMETER(dltotal); UNREFERENCED_PARAMETER(dlnow); - // Hack to smooth the progress bar - struct ProgressbarUpdater *myp = (struct ProgressbarUpdater *)clientp; - double curtime = 0; + if(myp->cancel) + return 1; + + double curtime = 0; curl_easy_getinfo(myp->curl, CURLINFO_TOTAL_TIME, &curtime); curl_off_t total_percen = 0; @@ -45,7 +47,13 @@ static size_t WriteMemoryCallback(char *contents, size_t size, size_t nmemb, voi } class SketchfabV2Uploader { +private: + struct ProgressbarUpdater prog; public: + void abort() + { + prog.cancel=true; + } std::pair upload(HWND progressBar, const std::string& token, const std::string& filepath, @@ -90,7 +98,6 @@ class SketchfabV2Uploader { HWND progressBar=NULL) { CURL *curl; - struct ProgressbarUpdater prog; CURLcode res; long http_code; std::string response; @@ -132,6 +139,7 @@ class SketchfabV2Uploader { if (curl) { prog.curl = curl; prog.progressBar = progressBar; + prog.cancel = false; curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); @@ -142,9 +150,14 @@ class SketchfabV2Uploader { curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); curl_easy_setopt(curl, CURLOPT_TIMEOUT, 900L); curl_easy_setopt(curl, CURLOPT_XFERINFOFUNCTION, progress_callback); + res = curl_easy_perform(curl); if (res != CURLE_OK) { - return std::pair(1, "{\"detail\":\"curl_easy_perform() failed: " + std::string(curl_easy_strerror(res)) + "\" } "); + // Upload has been cancelled + if(prog.cancel) + return std::pair(1, "{\"detail\":\" Canceled by the user\" } "); + else + return std::pair(1, "{\"detail\":\"curl_easy_perform() failed: " + std::string(curl_easy_strerror(res)) + "\" } "); } else { curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &http_code);