I use libcurl & libevent to build a project (like docs/examples/hiperfifo.c) . I found that the easy handle will be hang in some case such as network timeout.
After reading the libcurl code and testing, I found the reason is libcurl control the timeout is not exact.
This is my case:
1. set easy handle timeout is 80ms.
2. add easy handle to multi
3. when multi called the sock_cb, set the event, and set the timeout(80ms)
4. network timeout (easy handle read timeout)
5. libevent tell the curl timeout and curl call multi_socket function.
6. in multi_socket function, add_next_timeout will be called at last few line, and It will clean the timeoutlist for this easy handle because timeout occur. (at this moment, the easy hanle's state is CURLM_STATE_PERFORM)
7. next, it will call multi_runsingle function to process this easy handle, but in multi_runsingle function, Curl_timeleft will be called to check timeout occur or not. in Curl_timeleft it used the (now - t_startsingle). pay attention to this point, this may be 1ms, because Curl_tvdiff is not exact, such as : now(46151672,246084) - t_startsingle(46151672,166088) = 79ms, timeout is 80ms, so 80 - 79 = 1ms.
I think the logic for this code, I found that the real reason is that
"Curl_pgrsTime(data, TIMER_STARTSINGLE);" be called after "Curl_expire(data, data->set.timeout);" . I try to move the "Curl_pgrsTime(data, TIMER_STARTSINGLE);" before ""Curl_expire(data, data->set.timeout);" , the bad case never occur.
In a word, call the timer before set t_startsingle, will let libevet premature wake up the libcurl to process, and libcurl will think this not timeout.
of course, this bad case will occur fewly, but when this occur, the result will be very terrible.