]> granicus.if.org Git - curl/commitdiff
fix the alarm()-based DNS timeout
authorThomas Lopatic <lopatic@yahoo-inc.com>
Mon, 22 Mar 2010 20:57:48 +0000 (21:57 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 22 Mar 2010 20:57:48 +0000 (21:57 +0100)
Looking at the code of Curl_resolv_timeout() in hostip.c, I think
that in case of a timeout, the signal handler for SIGALRM never
gets removed. I think that in my case it gets executed at some
point later on when execution has long left Curl_resolv_timeout()
or even the cURL library.

The code that is jumped to with siglongjmp() simply sets the
error message to "name lookup timed out" and then returns with
CURLRESOLV_ERROR. I guess that instead of simply returning
without cleaning up, the code should have a goto that jumps to
the spot right after the call to Curl_resolv().

lib/hostip.c

index 4acf1217e6dea587860e392c2c4246557052c00d..68ceedc6d754b51fe169229b26b46a53fb00f12b 100644 (file)
@@ -571,15 +571,6 @@ int Curl_resolv_timeout(struct connectdata *conn,
     return CURLRESOLV_TIMEDOUT;
 
   if (timeout > 0) {
-    /* This allows us to time-out from the name resolver, as the timeout
-       will generate a signal and we will siglongjmp() from that here.
-       This technique has problems (see alarmfunc). */
-      if(sigsetjmp(curl_jmpenv, 1)) {
-        /* this is coming from a siglongjmp() after an alarm signal */
-        failf(data, "name lookup timed out");
-        return CURLRESOLV_ERROR;
-      }
-
     /*************************************************************
      * Set signal handler to catch SIGALRM
      * Store the old value to be able to set it back later!
@@ -605,6 +596,19 @@ int Curl_resolv_timeout(struct connectdata *conn,
     /* alarm() makes a signal get sent when the timeout fires off, and that
        will abort system calls */
     prev_alarm = alarm((unsigned int) (timeout/1000L));
+
+    /* This allows us to time-out from the name resolver, as the timeout
+       will generate a signal and we will siglongjmp() from that here.
+       This technique has problems (see alarmfunc).
+       This should be the last thing we do before calling Curl_resolv(),
+       as otherwise we'd have to worry about variables that get modified
+       before we invoke Curl_resolv() (and thus use "volatile"). */
+    if(sigsetjmp(curl_jmpenv, 1)) {
+      /* this is coming from a siglongjmp() after an alarm signal */
+      failf(data, "name lookup timed out");
+      rc = CURLRESOLV_ERROR;
+      goto clean_up;
+    }
   }
 
 #else
@@ -621,6 +625,8 @@ int Curl_resolv_timeout(struct connectdata *conn,
    */
   rc = Curl_resolv(conn, hostname, port, entry);
 
+clean_up:
+
 #ifdef USE_ALARM_TIMEOUT
   if (timeout > 0) {