we use signal() to ignore signals only as long as we have to, and we now
authorDaniel Stenberg <daniel@haxx.se>
Wed, 7 Nov 2001 14:13:29 +0000 (14:13 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Wed, 7 Nov 2001 14:13:29 +0000 (14:13 +0000)
restore the previous (if any) signal handler properly on return.

lib/transfer.c
lib/url.c

index 2d1c90f..163b2cb 100644 (file)
@@ -900,6 +900,10 @@ CURLcode Curl_perform(struct SessionHandle *data)
   struct connectdata *conn=NULL;
   bool port=TRUE; /* allow data->set.use_port to set port to use */
   char *newurl = NULL; /* possibly a new URL to follow to! */
+#ifdef HAVE_SIGNAL
+  /* storage for the previous signal handler */
+  void (*prev_signal)(int sig);
+#endif
 
   if(!data->change.url)
     /* we can't do anything wihout URL */
@@ -916,10 +920,23 @@ CURLcode Curl_perform(struct SessionHandle *data)
   data->state.this_is_a_follow = FALSE; /* reset this */
   data->state.errorbuf = FALSE; /* no error has occurred */
 
-  Curl_initinfo(data); /* reset session-specific information "variables" */
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
+  /*************************************************************
+   * Tell signal handler to ignore SIGPIPE
+   *************************************************************/
+  prev_signal = signal(SIGPIPE, SIG_IGN);
+#endif  
 
+  Curl_initinfo(data); /* reset session-specific information "variables" */
   Curl_pgrsStartNow(data);
 
+  /*
+   * It is important that there is NO 'return' from this function any any
+   * other place than falling down the bottom! This is because we have cleanup
+   * stuff that must be done before we get back, and that is only performed
+   * after this do-while loop.
+   */
+
   do {
     Curl_pgrsTime(data, TIMER_STARTSINGLE);
     res = Curl_connect(data, &conn, port);
@@ -1035,8 +1052,10 @@ CURLcode Curl_perform(struct SessionHandle *data)
              point to read-only data */
           char *url_clone=strdup(data->change.url);
 
-          if(!url_clone)
-            return CURLE_OUT_OF_MEMORY;
+          if(!url_clone) {
+            res = CURLE_OUT_OF_MEMORY;
+            break; /* skip out of this loop NOW */
+          }
 
           /* protsep points to the start of the host name */
           protsep=strstr(url_clone, "//");
@@ -1070,8 +1089,10 @@ CURLcode Curl_perform(struct SessionHandle *data)
                                  1 + /* possible slash */
                                  strlen(newurl) + 1/* zero byte */);
 
-          if(!newest)
-            return CURLE_OUT_OF_MEMORY;
+          if(!newest) {
+            res = CURLE_OUT_OF_MEMORY;
+            break; /* go go go out from this loop */
+          }
           sprintf(newest, "%s%s%s", url_clone, ('/' == newurl[0])?"":"/",
                   newurl);
           free(newurl);
@@ -1159,6 +1180,11 @@ CURLcode Curl_perform(struct SessionHandle *data)
   if(newurl)
     free(newurl);
 
+#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
+  /* restore the signal handler for SIGPIPE before we get back */
+  signal(SIGPIPE, prev_signal);
+#endif  
+
   return res;
 }
 
index 31e1459..079e957 100644 (file)
--- a/lib/url.c
+++ b/lib/url.c
@@ -143,13 +143,23 @@ RETSIGTYPE alarmfunc(int signal)
 }
 #endif
 
+
+/*
+ * This is the internal function curl_easy_cleanup() calls. This should
+ * cleanup and free all resources associated with this sessionhandle.
+ *
+ * NOTE: if we ever add something that attempts to write to a socket or
+ * similar here, we must ignore SIGPIPE first. It is currently only done
+ * when curl_easy_perform() is invoked.
+ */
+
 CURLcode Curl_close(struct SessionHandle *data)
 {
   /* Loop through all open connections and kill them one by one */
   while(-1 != ConnectionKillOne(data));
 
 #ifdef USE_SSLEAY
-  /* Close down all open info open SSL and sessions */
+  /* Close down all open SSL info and sessions */
   Curl_SSL_Close_All(data);
 #endif
 
@@ -258,13 +268,6 @@ CURLcode Curl_open(struct SessionHandle **curl)
 
   *curl = data;
 
-  /*************************************************************
-   * Tell signal handler to ignore SIGPIPE
-   *************************************************************/
-#if defined(HAVE_SIGNAL) && defined(SIGPIPE)
-  (void) signal(SIGPIPE, SIG_IGN);
-#endif
-  
   return CURLE_OK;
 }
 
@@ -1141,7 +1144,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 {
   char *tmp;
   char *buf;
-  CURLcode result;
+  CURLcode result=CURLE_OK;
   char resumerange[40]="";
   struct connectdata *conn;
   struct connectdata *conn_temp;
@@ -1154,6 +1157,10 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 #ifdef HAVE_SIGACTION
   struct sigaction keep_sigact;   /* store the old struct here */
   bool keep_copysig;              /* did copy it? */
+#else
+#ifdef HAVE_SIGNAL
+  void *keep_sigact;              /* store the old handler here */
+#endif
 #endif
 
   /*************************************************************
@@ -1941,7 +1948,7 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 #else
     /* no sigaction(), revert to the much lamer signal() */
 #ifdef HAVE_SIGNAL
-    signal(SIGALRM, alarmfunc);
+    keep_sigact = signal(SIGALRM, alarmfunc);
 #endif
 #endif
 
@@ -2006,6 +2013,11 @@ static CURLcode CreateConnection(struct SessionHandle *data,
          and clean */
       sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
     }
+#else
+#ifdef HAVE_SIGNAL
+    /* restore the previous SIGALRM handler */
+    signal(SIGALRM, keep_sigact);
+#endif
 #endif
     /* switch back the alarm() to either zero or to what it was before minus
        the time we spent until now! */