Commit fe3a78ab authored by Daniel Stenberg's avatar Daniel Stenberg
Browse files

we use signal() to ignore signals only as long as we have to, and we now

restore the previous (if any) signal handler properly on return.
parent 1a984ea8
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -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;
}

+22 −10
Original line number Diff line number Diff line
@@ -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! */