static CURLMcode add_next_timeout(struct curltime now,
struct Curl_multi *multi,
struct Curl_easy *d);
-static CURLMcode multi_timeout(struct Curl_multi *multi,
- struct curltime *expire_time,
- long *timeout_ms);
+static void multi_timeout(struct Curl_multi *multi,
+ struct curltime *expire_time,
+ long *timeout_ms);
static void process_pending_handles(struct Curl_multi *multi);
static void multi_xfer_bufs_free(struct Curl_multi *multi);
#ifdef DEBUGBUILD
multi->admin->multi = multi;
multi->admin->state.internal = TRUE;
Curl_llist_init(&multi->admin->state.timeoutlist, NULL);
+
#ifdef DEBUGBUILD
if(getenv("CURL_DEBUG"))
multi->admin->set.verbose = TRUE;
#endif
Curl_uint_tbl_add(&multi->xfers, multi->admin, &multi->admin->mid);
+ Curl_uint_bset_add(&multi->process, multi->admin->mid);
if(Curl_cshutdn_init(&multi->cshutdn, multi))
goto error;
return CURLM_OK;
}
-
CURLMcode curl_multi_add_handle(CURLM *m, CURL *d)
{
CURLMcode rc;
/* Make sure the new handle will run */
Curl_multi_mark_dirty(data);
+
/* Necessary in event based processing, where dirty handles trigger
* a timeout callback invocation. */
rc = Curl_update_timer(multi);
* poll. Collecting the sockets may install new timers by protocols
* and connection filters.
* Use the shorter one of the internal and the caller requested timeout. */
- (void)multi_timeout(multi, &expire_time, &timeout_internal);
+ multi_timeout(multi, &expire_time, &timeout_internal);
if((timeout_internal >= 0) && (timeout_internal < (long)timeout_ms))
timeout_ms = (int)timeout_internal;
long sleep_ms = 0;
/* Avoid busy-looping when there is nothing particular to wait for */
- if(!curl_multi_timeout(multi, &sleep_ms) && sleep_ms) {
+ multi_timeout(multi, &expire_time, &sleep_ms);
+ if(sleep_ms) {
if(sleep_ms > timeout_ms)
sleep_ms = timeout_ms;
/* when there are no easy handles in the multi, this holds a -1
* again during processing, triggering a re-run later. */
Curl_uint_bset_remove(&multi->dirty, data->mid);
+ if(data == multi->admin) {
+ Curl_cshutdn_perform(&multi->cshutdn, multi->admin, CURL_SOCKET_TIMEOUT);
+ return CURLM_OK;
+ }
+
do {
/* A "stream" here is a logical stream if the protocol can handle that
(HTTP/2), or the full connection for older protocols */
Curl_uint_bset_remove(&multi->dirty, mid);
continue;
}
- if(data != multi->admin) {
- /* admin handle is processed below */
- sigpipe_apply(data, &pipe_st);
- result = multi_runsingle(multi, &now, data);
- if(result)
- returncode = result;
- }
+ sigpipe_apply(data, &pipe_st);
+ result = multi_runsingle(multi, &now, data);
+ if(result)
+ returncode = result;
}
while(Curl_uint_bset_next(&multi->process, mid, &mid));
}
-
- sigpipe_apply(multi->admin, &pipe_st);
- Curl_cshutdn_perform(&multi->cshutdn, multi->admin, CURL_SOCKET_TIMEOUT);
sigpipe_restore(&pipe_st);
if(multi_ischanged(m, TRUE))
struct curltime now;
size_t run_xfers;
SIGPIPE_MEMBER(pipe_st);
- bool run_cpool;
};
static void multi_mark_expired_as_dirty(struct multi_run_ctx *mrc)
if(data) {
CURL_TRC_M(data, "multi_run_dirty");
- if(data == multi->admin) {
- Curl_uint_bset_remove(&multi->dirty, mid);
- mrc->run_cpool = TRUE;
- continue;
- }
- else if(!Curl_uint_bset_contains(&multi->process, mid)) {
+ if(!Curl_uint_bset_contains(&multi->process, mid)) {
/* We are no longer processing this transfer */
Curl_uint_bset_remove(&multi->dirty, mid);
continue;
/* Reassess event status of all active transfers */
result = Curl_multi_ev_assess_xfer_bset(multi, &multi->process);
}
- mrc.run_cpool = TRUE;
goto out;
}
if(s != CURL_SOCKET_TIMEOUT) {
/* Mark all transfers of that socket as dirty */
- Curl_multi_ev_dirty_xfers(multi, s, &mrc.run_cpool);
+ Curl_multi_ev_dirty_xfers(multi, s);
}
else {
/* Asked to run due to time-out. Clear the 'last_expire_ts' variable to
handles the case when the application asks libcurl to run the timeout
prematurely. */
memset(&multi->last_expire_ts, 0, sizeof(multi->last_expire_ts));
- mrc.run_cpool = TRUE;
}
multi_mark_expired_as_dirty(&mrc);
}
out:
- if(mrc.run_cpool) {
- sigpipe_apply(multi->admin, &mrc.pipe_st);
- Curl_cshutdn_perform(&multi->cshutdn, multi->admin, s);
- }
sigpipe_restore(&mrc.pipe_st);
if(multi_ischanged(multi, TRUE))
return FALSE;
}
-static CURLMcode multi_timeout(struct Curl_multi *multi,
- struct curltime *expire_time,
- long *timeout_ms)
+static void multi_timeout(struct Curl_multi *multi,
+ struct curltime *expire_time,
+ long *timeout_ms)
{
static const struct curltime tv_zero = {0, 0};
#ifndef CURL_DISABLE_VERBOSE_STRINGS
if(multi->dead) {
*timeout_ms = 0;
- return CURLM_OK;
+ return;
}
if(multi_has_dirties(multi)) {
*expire_time = curlx_now();
*timeout_ms = 0;
- return CURLM_OK;
+ return;
}
else if(multi->timetree) {
/* we have a tree of expire times */
}
}
#endif
-
- return CURLM_OK;
}
CURLMcode curl_multi_timeout(CURLM *m,
if(multi->in_callback)
return CURLM_RECURSIVE_API_CALL;
- return multi_timeout(multi, &expire_time, timeout_ms);
+ multi_timeout(multi, &expire_time, timeout_ms);
+ return CURLM_OK;
}
/*
if(!multi->timer_cb || multi->dead)
return CURLM_OK;
- if(multi_timeout(multi, &expire_ts, &timeout_ms)) {
- return CURLM_OK;
- }
+ multi_timeout(multi, &expire_ts, &timeout_ms);
if(timeout_ms < 0 && multi->last_timeout_ms < 0) {
/* nothing to do */
curl_off_t *pvalue)
{
struct Curl_multi *multi = m;
+ unsigned int n;
if(!GOOD_MULTI_HANDLE(multi))
return CURLM_BAD_HANDLE;
return CURLM_BAD_FUNCTION_ARGUMENT;
switch(info) {
- case CURLMINFO_XFERS_CURRENT: {
- unsigned int n = Curl_uint_tbl_count(&multi->xfers);
+ case CURLMINFO_XFERS_CURRENT:
+ n = Curl_uint_tbl_count(&multi->xfers);
if(n && multi->admin)
--n;
*pvalue = (curl_off_t)n;
return CURLM_OK;
- }
case CURLMINFO_XFERS_RUNNING:
- *pvalue = (curl_off_t)Curl_uint_bset_count(&multi->process);
+ n = Curl_uint_bset_count(&multi->process);
+ if(n && Curl_uint_bset_contains(&multi->process, multi->admin->mid))
+ --n;
+ *pvalue = (curl_off_t)n;
return CURLM_OK;
case CURLMINFO_XFERS_PENDING:
*pvalue = (curl_off_t)Curl_uint_bset_count(&multi->pending);
struct Curl_easy *Curl_multi_get_easy(struct Curl_multi *multi,
unsigned int mid)
{
- struct Curl_easy *data = mid ? Curl_uint_tbl_get(&multi->xfers, mid) : NULL;
+ struct Curl_easy *data = Curl_uint_tbl_get(&multi->xfers, mid);
if(data && GOOD_EASY_HANDLE(data))
return data;
CURL_TRC_M(multi->admin, "invalid easy handle in xfer table for mid=%u",