]> granicus.if.org Git - curl/commitdiff
multi_socket: improved 100-continue timeout handling
authorDaniel Stenberg <daniel@haxx.se>
Tue, 27 Aug 2013 20:32:51 +0000 (22:32 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 27 Aug 2013 22:07:12 +0000 (00:07 +0200)
When waiting for a 100-continue response from the server, the
Curl_readwrite() will refuse to run if called until the timeout has been
reached.

We timeout code in multi_socket() allows code to run slightly before the
actual timeout time, so for test 154 it could lead to the function being
executed but refused in Curl_readwrite() and then the application would
just sit idling forever.

This was detected with runtests.pl -e on test 154.

lib/easy.c
lib/multi.c
lib/multiif.h
lib/transfer.c

index b7507019b97bba11edcbc9b8af942b336d1983b4..32a61a9f86db72bcec070258c087f67bd9102f24 100644 (file)
@@ -489,7 +489,6 @@ static int events_timer(CURLM *multi,    /* multi handle */
 
   ev->ms = timeout_ms;
   ev->msbump = TRUE;
-  /* fprintf(stderr, "%s: timeout %ld\n", __func__, timeout_ms); */
   return 0;
 }
 
@@ -647,8 +646,6 @@ static CURLcode wait_or_timeout(struct Curl_multi *multi, struct events *ev)
     /* get the time stamp to use to figure out how long poll takes */
     before = curlx_tvnow();
 
-    /* fprintf(stderr, "poll(), %d numfds\n", numfds); */
-
     /* wait for activity or timeout */
     pollrc = Curl_poll(fds, numfds, (int)ev->ms);
 
@@ -793,15 +790,14 @@ static CURLcode easy_transfer(CURLM *multi)
  * DEBUG: if 'events' is set TRUE, this function will use a replacement engine
  * instead of curl_multi_perform() and use curl_multi_socket_action().
  */
-static CURLcode easy_perform(CURL *easy, bool events)
+static CURLcode easy_perform(struct SessionHandle *data, bool events)
 {
   CURLM *multi;
   CURLMcode mcode;
   CURLcode code = CURLE_OK;
-  struct SessionHandle *data = easy;
   SIGPIPE_VARIABLE(pipe_st);
 
-  if(!easy)
+  if(!data)
     return CURLE_BAD_FUNCTION_ARGUMENT;
 
   if(data->multi) {
@@ -823,7 +819,7 @@ static CURLcode easy_perform(CURL *easy, bool events)
   /* Copy the MAXCONNECTS option to the multi handle */
   curl_multi_setopt(multi, CURLMOPT_MAXCONNECTS, data->set.maxconnects);
 
-  mcode = curl_multi_add_handle(multi, easy);
+  mcode = curl_multi_add_handle(multi, data);
   if(mcode) {
     curl_multi_cleanup(multi);
     if(mcode == CURLM_OUT_OF_MEMORY)
@@ -843,7 +839,7 @@ static CURLcode easy_perform(CURL *easy, bool events)
 
   /* ignoring the return code isn't nice, but atm we can't really handle
      a failure here, room for future improvement! */
-  (void)curl_multi_remove_handle(multi, easy);
+  (void)curl_multi_remove_handle(multi, data);
 
   sigpipe_restore(&pipe_st);
 
index 6b4236198d0237d3c54c619519b42ac3cab94a77..fb495e078cd5b8dfe5508f827cab7ca6226faacc 100644 (file)
@@ -2104,12 +2104,6 @@ static CURLMcode add_next_timeout(struct timeval now,
   return CURLM_OK;
 }
 
-#ifdef WIN32
-#define TIMEOUT_INACCURACY 40000
-#else
-#define TIMEOUT_INACCURACY 3000
-#endif
-
 static CURLMcode multi_socket(struct Curl_multi *multi,
                               bool checkall,
                               curl_socket_t s,
@@ -2215,7 +2209,7 @@ static CURLMcode multi_socket(struct Curl_multi *multi,
      margin.
   */
 
-  now.tv_usec += TIMEOUT_INACCURACY;
+  now.tv_usec += MULTI_TIMEOUT_INACCURACY;
   if(now.tv_usec >= 1000000) {
     now.tv_sec++;
     now.tv_usec -= 1000000;
index d1b0e2fb3238b8a0e0add36cb373fd26a4262513..e61c5c6f2c9fd0a80d2a7a608357d944b6dd2c16 100644 (file)
  *
  ***************************************************************************/
 
-
+/* See multi_socket() for the explanation of this constant. Counted in number
+   of microseconds. */
+#ifdef WIN32
+#define MULTI_TIMEOUT_INACCURACY 40000
+#else
+#define MULTI_TIMEOUT_INACCURACY 3000
+#endif
 
 /*
  * Prototypes for library-wide functions provided by multi.c
index 31553eb46f28b095fc20cca5064352bb7afa01ba..760e79d9fb4d1b793ae16c7206c02a0250fd0b5b 100644 (file)
@@ -1952,8 +1952,10 @@ Curl_setup_transfer(
         k->exp100 = EXP100_AWAITING_CONTINUE;
         k->start100 = Curl_tvnow();
 
-        /* set a timeout for the multi interface */
-        Curl_expire(data, CURL_TIMEOUT_EXPECT_100);
+        /* Set a timeout for the multi interface. Add the inaccuracy margin so
+           that we don't fire slightly too early and get denied to run. */
+        Curl_expire(data, CURL_TIMEOUT_EXPECT_100 +
+                    MULTI_TIMEOUT_INACCURACY / 1000);
       }
       else {
         if(data->state.expect100header)