summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzmike <michael.blumenkrantz@gmail.com>2015-01-02 23:21:34 -0500
committerzmike <michael.blumenkrantz@gmail.com>2015-01-02 23:21:55 -0500
commitf55c756c17b9567a643c7f779c65433f3c6eb9ca (patch)
tree6f0d774c9a9402da1e60d7aa26a4c291d72e682f
parenta68ded6ab63deb3e7a632693840ad31473bf87f2 (diff)
downloadefl-f55c756c17b9567a643c7f779c65433f3c6eb9ca.tar.gz
curl usage better accounts for timeouts
curl is dumb. it needs to poll its own fd for data, it gets confused with its own timeouts, and sometimes it forgets that it's supposed to be doing anything. this fixes: * connection timeout processing * connection data processing order also curl_multi_timeout calls are now done from a single function to handle all of this stupidness in one place maybe backport after more testing...
-rw-r--r--src/lib/ecore_con/ecore_con_url.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/src/lib/ecore_con/ecore_con_url.c b/src/lib/ecore_con/ecore_con_url.c
index 2c5dc0ce5f..11a2abce12 100644
--- a/src/lib/ecore_con/ecore_con_url.c
+++ b/src/lib/ecore_con/ecore_con_url.c
@@ -276,6 +276,7 @@ static Eina_List *_fd_hd_list = NULL;
static int _init_count = 0;
static Ecore_Timer *_curl_timer = NULL;
static Eina_Bool pipelining = EINA_FALSE;
+static long last_ms = -1;
static Ecore_Con_Curl *_c = NULL;
static Eina_Bool _c_fail = EINA_FALSE;
@@ -343,7 +344,8 @@ _c_init(void)
goto error;
}
_c->curl_multi_timeout(_c->_curlm, &ms);
- if ((ms >= CURL_MIN_TIMEOUT) || (ms <= 0)) ms = CURL_MIN_TIMEOUT;
+ if ((ms >= CURL_MIN_TIMEOUT) || (ms < 0)) ms = CURL_MIN_TIMEOUT;
+ last_ms = ms;
_curl_timer = ecore_timer_add((double)ms / 1000.0,
_ecore_con_url_timer, NULL);
ecore_timer_freeze(_curl_timer);
@@ -1519,20 +1521,53 @@ _ecore_con_url_curl_clear(void)
ecore_main_fd_handler_del(fdh);
EINA_LIST_FREE(_url_con_list, url_con)
_ecore_con_url_multi_remove(url_con);
+ last_ms = -1;
+}
+
+static Eina_Bool
+_ecore_con_url_do_multi_timeout(long *retms)
+{
+ long ms = 0;
+ int ret;
+
+ while (!ms)
+ {
+ ret = _c->curl_multi_timeout(_c->_curlm, &ms);
+ *retms = ms;
+ if ((last_ms > 0) && (ms < 0))
+ ERR("curl_multi_perform() timeout");
+ else if (ms <= 0)
+ {
+ last_ms = ms;
+ _ecore_con_url_timer(NULL);
+ DBG("multiperform is still running: timeout: %ld", ms);
+ return EINA_TRUE;
+ }
+ else if ((ret <= 0) && (ms > 0)) break;
+ else
+ ERR("curl_multi_perform() failed: %s", _c->curl_multi_strerror(ret));
+ last_ms = ms;
+ _ecore_con_url_curl_clear();
+ ecore_timer_freeze(_curl_timer);
+ return EINA_FALSE;
+ }
+ return EINA_TRUE;
}
static Eina_Bool
_ecore_con_url_fd_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler EINA_UNUSED)
{
Ecore_Fd_Handler *fdh;
- long ms;
+ long ms = 0;
if (!_c) return ECORE_CALLBACK_CANCEL;
EINA_LIST_FREE(_fd_hd_list, fdh)
ecore_main_fd_handler_del(fdh);
- _c->curl_multi_timeout(_c->_curlm, &ms);
+ if (!_ecore_con_url_do_multi_timeout(&ms)) return EINA_FALSE;
+ last_ms = ms;
if ((ms >= CURL_MIN_TIMEOUT) || (ms <= 0)) ms = CURL_MIN_TIMEOUT;
ecore_timer_interval_set(_curl_timer, (double)ms / 1000.0);
+ ecore_timer_reset(_curl_timer);
_ecore_con_url_timer(NULL);
return ECORE_CALLBACK_CANCEL;
}
@@ -1594,6 +1629,7 @@ _ecore_con_url_timer(void *data EINA_UNUSED)
if (ret == CURLM_CALL_MULTI_PERFORM)
{
DBG("curl_multi_perform() again immediately");
+ ecore_timer_interval_set(_curl_timer, 0.000001);
return ECORE_CALLBACK_RENEW;
}
else if (ret != CURLM_OK)
@@ -1604,13 +1640,14 @@ _ecore_con_url_timer(void *data EINA_UNUSED)
}
if (still_running)
{
- long ms;
+ long ms = 0;
_ecore_con_url_fdset();
- _c->curl_multi_timeout(_c->_curlm, &ms);
+ if (!_ecore_con_url_do_multi_timeout(&ms)) return EINA_FALSE;
+ last_ms = ms;
DBG("multiperform is still running: %d, timeout: %ld",
still_running, ms);
- if ((ms >= CURL_MIN_TIMEOUT) || (ms <= 0)) ms = CURL_MIN_TIMEOUT;
+ if ((ms >= CURL_MIN_TIMEOUT) || (ms < 0)) ms = CURL_MIN_TIMEOUT;
ecore_timer_interval_set(_curl_timer, (double)ms / 1000.0);
}
else