Bug fix for previous commit.

This commit is contained in:
Aleric Inglewood
2012-10-08 04:57:22 +02:00
parent 1252b0bde2
commit 6a4f76a219
3 changed files with 41 additions and 17 deletions

View File

@@ -88,6 +88,9 @@ void AICurlEasyRequestStateMachine::finished(AICurlEasyRequest_wat&)
// CURL-THREAD // CURL-THREAD
void AICurlEasyRequestStateMachine::removed_from_multi_handle(AICurlEasyRequest_wat&) void AICurlEasyRequestStateMachine::removed_from_multi_handle(AICurlEasyRequest_wat&)
{ {
llassert(mFinished || mTimedOut); // If we neither finished nor timed out, then why is this being removed?
// Note that allowing this would cause an assertion later on for removing
// a CurlResponderBuffer with a still active Responder.
set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed); set_state(mFinished ? AICurlEasyRequestStateMachine_removed_after_finished : AICurlEasyRequestStateMachine_removed);
} }

View File

@@ -1374,13 +1374,16 @@ MultiHandle::~MultiHandle()
void MultiHandle::handle_stalls(void) void MultiHandle::handle_stalls(void)
{ {
for(addedEasyRequests_type::iterator iter = mAddedEasyRequests.begin(); iter != mAddedEasyRequests.end(); iter = mAddedEasyRequests.begin()) for(addedEasyRequests_type::iterator iter = mAddedEasyRequests.begin(); iter != mAddedEasyRequests.end();)
{ {
if (AICurlEasyRequest_wat(**iter)->timeout_has_stalled()) if (AICurlEasyRequest_wat(**iter)->timeout_has_stalled())
{ {
Dout(dc::curl, "MultiHandle::handle_stalls(): Easy request stalled! [" << (void*)iter->get_ptr().get() << "]"); Dout(dc::curl, "MultiHandle::handle_stalls(): Easy request stalled! [" << (void*)iter->get_ptr().get() << "]");
remove_easy_request(*iter, false); finish_easy_request(*iter, CURLE_OPERATION_TIMEDOUT);
remove_easy_request(iter++, false);
} }
else
++iter;
} }
} }
@@ -1527,6 +1530,11 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request
} }
return (CURLMcode)-2; // Was already removed before, or never added (queued). return (CURLMcode)-2; // Was already removed before, or never added (queued).
} }
return remove_easy_request(iter, as_per_command);
}
CURLMcode MultiHandle::remove_easy_request(addedEasyRequests_type::iterator const& iter, bool as_per_command)
{
CURLMcode res; CURLMcode res;
{ {
AICurlEasyRequest_wat curl_easy_request_w(**iter); AICurlEasyRequest_wat curl_easy_request_w(**iter);
@@ -1535,9 +1543,12 @@ CURLMcode MultiHandle::remove_easy_request(AICurlEasyRequest const& easy_request
curl_easy_request_w->mRemovedPerCommand = as_per_command; curl_easy_request_w->mRemovedPerCommand = as_per_command;
#endif #endif
} }
#if CWDEBUG
ThreadSafeCurlEasyRequest* lockobj = iter->get_ptr().get();
#endif
mAddedEasyRequests.erase(iter); mAddedEasyRequests.erase(iter);
mHandleAddedOrRemoved = true; mHandleAddedOrRemoved = true;
Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)easy_request.get_ptr().get() << "; now processing " << mAddedEasyRequests.size() << " easy handles."); Dout(dc::curl, "MultiHandle::remove_easy_request: Removed AICurlEasyRequest " << (void*)lockobj << "; now processing " << mAddedEasyRequests.size() << " easy handles.");
// Attempt to add a queued request, if any. // Attempt to add a queued request, if any.
if (!mQueuedRequests.empty()) if (!mQueuedRequests.empty())
@@ -1565,20 +1576,8 @@ void MultiHandle::check_run_count(void)
llassert_always(rese == CURLE_OK); llassert_always(rese == CURLE_OK);
AICurlEasyRequest easy_request(ptr); AICurlEasyRequest easy_request(ptr);
llassert(*AICurlEasyRequest_wat(*easy_request) == easy); llassert(*AICurlEasyRequest_wat(*easy_request) == easy);
// Store the result and transfer info in the easy handle. // Store result and trigger events for the easy request.
{ finish_easy_request(easy_request, msg->data.result);
AICurlEasyRequest_wat curl_easy_request_w(*easy_request);
curl_easy_request_w->store_result(msg->data.result);
#ifdef CWDEBUG
char* eff_url;
curl_easy_request_w->getinfo(CURLINFO_EFFECTIVE_URL, &eff_url);
Dout(dc::curl, "Finished: " << eff_url << " (" << curl_easy_strerror(msg->data.result) << ") [CURLINFO_PRIVATE = " << (void*)ptr << "]");
#endif
// Update timeout administration.
curl_easy_request_w->timeout_done(msg->data.result);
// Signal that this easy handle finished.
curl_easy_request_w->done(curl_easy_request_w);
}
// This invalidates msg, but not easy_request. // This invalidates msg, but not easy_request.
CURLMcode res = remove_easy_request(easy_request); CURLMcode res = remove_easy_request(easy_request);
// This should hold, I think, because the handles are obviously ok and // This should hold, I think, because the handles are obviously ok and
@@ -1602,6 +1601,22 @@ void MultiHandle::check_run_count(void)
mPrevRunningHandles = mRunningHandles; mPrevRunningHandles = mRunningHandles;
} }
void MultiHandle::finish_easy_request(AICurlEasyRequest const& easy_request, CURLcode result)
{
AICurlEasyRequest_wat curl_easy_request_w(*easy_request);
// Store the result in the easy handle.
curl_easy_request_w->store_result(result);
#ifdef CWDEBUG
char* eff_url;
curl_easy_request_w->getinfo(CURLINFO_EFFECTIVE_URL, &eff_url);
Dout(dc::curl, "Finished: " << eff_url << " (" << curl_easy_strerror(result) << ") [CURLINFO_PRIVATE = " << (void*)easy_request.get_ptr().get() << "]");
#endif
// Update timeout administration.
curl_easy_request_w->timeout_done(result);
// Signal that this easy handle finished.
curl_easy_request_w->done(curl_easy_request_w);
}
} // namespace curlthread } // namespace curlthread
} // namespace AICurlPrivate } // namespace AICurlPrivate

View File

@@ -82,6 +82,12 @@ class MultiHandle : public CurlMultiHandle
long mTimeOut; // The last time out in ms as set by the callback CURLMOPT_TIMERFUNCTION. long mTimeOut; // The last time out in ms as set by the callback CURLMOPT_TIMERFUNCTION.
private: private:
// Store result and trigger events for easy request.
void finish_easy_request(AICurlEasyRequest const& easy_request, CURLcode result);
// Remove easy request at iter (must exist).
// Note that it's possible that a new request from mQueuedRequests is inserted before iter.
CURLMcode remove_easy_request(addedEasyRequests_type::iterator const& iter, bool as_per_command);
static int socket_callback(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp); static int socket_callback(CURL* easy, curl_socket_t s, int action, void* userp, void* socketp);
static int timer_callback(CURLM* multi, long timeout_ms, void* userp); static int timer_callback(CURLM* multi, long timeout_ms, void* userp);