@@ -274,6 +274,24 @@ int CurlMultiDebugCallback(CURL *handle, curl_infotype type, char *data, size_t
274
274
return 0 ;
275
275
}
276
276
277
+ void CurlMultiHttpClient::CurlMultiPerformReset ()
278
+ {
279
+ // TODO: refactor
280
+ std::unique_lock<std::mutex> lockGuard (m_signalMutex);
281
+ std::unique_lock<std::mutex> lock (m_tasksMutex);
282
+ AWS_LOGSTREAM_ERROR (CURL_HTTP_CLIENT_TAG, " Removing all easy handles from a multi handle and triggering callbacks." );
283
+
284
+ for (Curl::CurlEasyHandleContext* handleCtx : m_multiTasks)
285
+ {
286
+ curl_multi_remove_handle (m_curlMultiHandleContainer.AccessCurlMultiHandle (), handleCtx->m_curlEasyHandle );
287
+ handleCtx->curlResultMsg = nullptr ;
288
+ handleCtx->curlResult = static_cast <CURLcode>(-1 );
289
+ handleCtx->m_onCurlDoneFn ();
290
+ m_multiTasks.erase (handleCtx);
291
+ }
292
+ m_multiTasks.clear ();
293
+ }
294
+
277
295
void CurlMultiHttpClient::CurlMultiPerformThread (CurlMultiHttpClient* pClient)
278
296
{
279
297
assert (pClient && pClient->m_curlMultiHandleContainer .AccessCurlMultiHandle ());
@@ -297,12 +315,18 @@ void CurlMultiHttpClient::CurlMultiPerformThread(CurlMultiHttpClient* pClient)
297
315
}
298
316
if (!pClient->m_isRunning .load ())
299
317
{
300
- break ;
318
+ break ;
301
319
}
302
320
303
321
pClient->m_tasksQueued = 0 ;
304
322
305
323
CURLMcode mc = curl_multi_perform (multi_handle, &stillRunning);
324
+ if (mc != CURLM_OK)
325
+ {
326
+ AWS_LOGSTREAM_ERROR (CURL_HTTP_CLIENT_TAG, " Curl curl_multi_perform returned error code " << mc
327
+ << " resetting multi handle." );
328
+ pClient->CurlMultiPerformReset ();
329
+ }
306
330
int msgQueue = 0 ;
307
331
do {
308
332
@@ -326,12 +350,14 @@ void CurlMultiHttpClient::CurlMultiPerformThread(CurlMultiHttpClient* pClient)
326
350
} while (msgQueue > 0 );
327
351
328
352
if (!mc && stillRunning)
329
- /* wait for activity, timeout or "nothing" */
330
- mc = curl_multi_poll (multi_handle, NULL , 0 , 1000 , NULL );
331
-
332
- if (mc) {
333
- fprintf (stderr, " curl_multi_poll() failed, code %d.\n " , (int )mc);
334
- break ;
353
+ {
354
+ /* wait for activity, timeout or "nothing" */
355
+ mc = curl_multi_poll (multi_handle, NULL , 0 , 1000 , NULL );
356
+ if (mc)
357
+ {
358
+ AWS_LOGSTREAM_ERROR (CURL_HTTP_CLIENT_TAG, " Curl curl_multi_poll returned error code " << mc);
359
+ break ;
360
+ }
335
361
}
336
362
};
337
363
}
@@ -705,6 +731,10 @@ std::shared_ptr<HttpResponse> CurlMultiHttpClient::HandleCurlResponse(Curl::Curl
705
731
}
706
732
707
733
curl_multi_remove_handle (client->m_curlMultiHandleContainer .AccessCurlMultiHandle (), connectionHandle);
734
+ {
735
+ std::unique_lock<std::mutex> lock (client->m_tasksMutex );
736
+ client->m_multiTasks .erase (pEasyHandleCtx);
737
+ }
708
738
709
739
std::shared_ptr<HttpResponse> res = std::move (pEasyHandleCtx->writeContext .m_response );
710
740
pEasyHandleCtx->writeContext .m_response .reset ();
@@ -721,19 +751,27 @@ std::shared_ptr<HttpResponse> CurlMultiHttpClient::HandleCurlResponse(Curl::Curl
721
751
return res;
722
752
}
723
753
724
- void CurlMultiHttpClient::SubmitTask (Curl::CurlEasyHandleContext* pEasyHandleCtx) const
754
+ bool CurlMultiHttpClient::SubmitTask (Curl::CurlEasyHandleContext* pEasyHandleCtx) const
725
755
{
726
756
assert (pEasyHandleCtx);
727
- AWS_UNREFERENCED_PARAM (pEasyHandleCtx);
757
+ CURLMcode curlMultiResponseCode = curl_multi_add_handle (m_curlMultiHandleContainer.AccessCurlMultiHandle (),
758
+ pEasyHandleCtx->m_curlEasyHandle );
759
+ if (CURLM_OK != curlMultiResponseCode)
760
+ {
761
+ return false ;
762
+ }
763
+
728
764
{
729
765
std::unique_lock<std::mutex> lock (m_tasksMutex);
766
+ m_multiTasks.insert (pEasyHandleCtx);
730
767
m_tasksQueued++;
731
768
}
732
769
{
733
770
std::unique_lock<std::mutex> lockGuard (m_signalMutex);
734
771
m_signalRunning.notify_one ();
735
772
curl_multi_wakeup (m_curlMultiHandleContainer.AccessCurlMultiHandle ());
736
773
}
774
+ return true ;
737
775
}
738
776
739
777
// Blocking
@@ -774,18 +812,14 @@ std::shared_ptr<HttpResponse> CurlMultiHttpClient::MakeRequest(const std::shared
774
812
775
813
easyHandleContext->startTransmissionTime = Aws::Utils::DateTime::Now ();
776
814
777
- CURLMcode curlMultiResponseCode = curl_multi_add_handle (m_curlMultiHandleContainer.AccessCurlMultiHandle (),
778
- easyHandleContext->m_curlEasyHandle );
779
- if (CURLM_OK != curlMultiResponseCode)
815
+ if (!SubmitTask (easyHandleContext))
780
816
{
781
- response->SetClientErrorType (CoreErrors::NETWORK_CONNECTION);
782
- response->SetClientErrorMessage (" Failed to add curl_easy_handle to curl_multi_handle." );
783
- AWS_LOGSTREAM_ERROR (CURL_HTTP_CLIENT_TAG, " Failed to add curl_easy_handle to curl_multi_handle." );
784
- return response;
817
+ response->SetClientErrorType (CoreErrors::NETWORK_CONNECTION);
818
+ response->SetClientErrorMessage (" Failed to add curl_easy_handle to curl_multi_handle." );
819
+ AWS_LOGSTREAM_ERROR (CURL_HTTP_CLIENT_TAG, " Failed to add curl_easy_handle to curl_multi_handle." );
820
+ return response;
785
821
}
786
822
787
- SubmitTask (easyHandleContext);
788
-
789
823
// Task submitted, wait for it's completion
790
824
std::unique_lock<std::mutex> lockGuard (taskMutex);
791
825
signal.wait (lockGuard,
0 commit comments