myalarm() is history, we now use HAVE_ALARM and we now do our very best to
1 - restore the previous sigaction struct as soon as we are about to shut off our timeout 2 - restore the previous alarm() timeout, in case an application or similar had it running before we "borrowed" it for a while. No, this does not fix the multi-thread problem you get with alarm(). This patch should correct bug report #478780: //sourceforge.net/tracker/?func=detail&atid=100976&aid=478780&group_id=976 If not, please post details!
This commit is contained in:
		@@ -110,13 +110,13 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
 | 
			
		||||
#define sclose(x) closesocket(x)
 | 
			
		||||
#define sread(x,y,z) recv(x,y,z,0)
 | 
			
		||||
#define swrite(x,y,z) (size_t)send(x,y,z,0)
 | 
			
		||||
#define myalarm(x) /* win32 is a silly system */
 | 
			
		||||
#undef HAVE_ALARM
 | 
			
		||||
#else
 | 
			
		||||
     /* gcc-for-win is still good :) */
 | 
			
		||||
#define sclose(x) close(x)
 | 
			
		||||
#define sread(x,y,z) recv(x,y,z,0)
 | 
			
		||||
#define swrite(x,y,z) send(x,y,z,0)
 | 
			
		||||
#define myalarm(x) alarm(x)
 | 
			
		||||
#define HAVE_ALARM
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define PATH_CHAR     ";"
 | 
			
		||||
@@ -127,7 +127,7 @@ defined(HAVE_LIBSSL) && defined(HAVE_LIBCRYPTO)
 | 
			
		||||
#define sclose(x) close(x)
 | 
			
		||||
#define sread(x,y,z) recv(x,y,z,0)
 | 
			
		||||
#define swrite(x,y,z) send(x,y,z,0)
 | 
			
		||||
#define myalarm(x) alarm(x)
 | 
			
		||||
#define HAVE_ALARM
 | 
			
		||||
 | 
			
		||||
#define PATH_CHAR     ":"
 | 
			
		||||
#define DIR_CHAR      "/"
 | 
			
		||||
 
 | 
			
		||||
@@ -1159,10 +1159,6 @@ CURLcode Curl_perform(struct SessionHandle *data)
 | 
			
		||||
  if(newurl)
 | 
			
		||||
    free(newurl);
 | 
			
		||||
 | 
			
		||||
  /* make absolutely sure the alarm is switched off! */
 | 
			
		||||
  if(data->set.timeout || data->set.connecttimeout)
 | 
			
		||||
    myalarm(0);
 | 
			
		||||
 | 
			
		||||
  return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										112
									
								
								lib/url.c
									
									
									
									
									
								
							
							
						
						
									
										112
									
								
								lib/url.c
									
									
									
									
									
								
							@@ -72,7 +72,6 @@
 | 
			
		||||
#include <inet.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef HAVE_SELECT
 | 
			
		||||
#error "We can't compile without select() support!"
 | 
			
		||||
#endif
 | 
			
		||||
@@ -200,10 +199,6 @@ CURLcode Curl_open(struct SessionHandle **curl)
 | 
			
		||||
{
 | 
			
		||||
  /* We don't yet support specifying the URL at this point */
 | 
			
		||||
  struct SessionHandle *data;
 | 
			
		||||
#ifdef HAVE_SIGACTION
 | 
			
		||||
  struct sigaction sigact;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /* Very simple start-up: alloc the struct, init it with zeroes and return */
 | 
			
		||||
  data = (struct SessionHandle *)malloc(sizeof(struct SessionHandle));
 | 
			
		||||
  if(!data)
 | 
			
		||||
@@ -263,24 +258,6 @@ CURLcode Curl_open(struct SessionHandle **curl)
 | 
			
		||||
 | 
			
		||||
  *curl = data;
 | 
			
		||||
 | 
			
		||||
  /*************************************************************
 | 
			
		||||
   * Set signal handler to catch SIGALRM
 | 
			
		||||
   *************************************************************/
 | 
			
		||||
#ifdef HAVE_SIGACTION
 | 
			
		||||
  sigaction(SIGALRM, NULL, &sigact);
 | 
			
		||||
  sigact.sa_handler = alarmfunc;
 | 
			
		||||
#ifdef SA_RESTART
 | 
			
		||||
  /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
 | 
			
		||||
  sigact.sa_flags &= ~SA_RESTART;
 | 
			
		||||
#endif
 | 
			
		||||
  sigaction(SIGALRM, &sigact, NULL);
 | 
			
		||||
#else
 | 
			
		||||
  /* no sigaction(), revert to the much lamer signal() */
 | 
			
		||||
#ifdef HAVE_SIGNAL
 | 
			
		||||
  signal(SIGALRM, alarmfunc);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /*************************************************************
 | 
			
		||||
   * Tell signal handler to ignore SIGPIPE
 | 
			
		||||
   *************************************************************/
 | 
			
		||||
@@ -1170,6 +1147,14 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 | 
			
		||||
  struct connectdata *conn_temp;
 | 
			
		||||
  char endbracket;
 | 
			
		||||
  int urllen;
 | 
			
		||||
#ifdef HAVE_ALARM
 | 
			
		||||
  unsigned int prev_alarm;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SIGACTION
 | 
			
		||||
  struct sigaction keep_sigact;   /* store the old struct here */
 | 
			
		||||
  bool keep_copysig;              /* did copy it? */
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
  /*************************************************************
 | 
			
		||||
   * Check input data
 | 
			
		||||
@@ -1937,17 +1922,43 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 | 
			
		||||
   * Set timeout if that is being used
 | 
			
		||||
   *************************************************************/
 | 
			
		||||
  if(data->set.timeout || data->set.connecttimeout) {
 | 
			
		||||
    /*************************************************************
 | 
			
		||||
     * Set signal handler to catch SIGALRM
 | 
			
		||||
     * Store the old value to be able to set it back later!
 | 
			
		||||
     *************************************************************/
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_SIGACTION
 | 
			
		||||
    struct sigaction sigact;
 | 
			
		||||
    sigaction(SIGALRM, NULL, &sigact);
 | 
			
		||||
    sigact.sa_handler = alarmfunc;
 | 
			
		||||
#ifdef SA_RESTART
 | 
			
		||||
    /* HPUX doesn't have SA_RESTART but defaults to that behaviour! */
 | 
			
		||||
    sigact.sa_flags &= ~SA_RESTART;
 | 
			
		||||
#endif
 | 
			
		||||
    /* now set the new struct */
 | 
			
		||||
    sigaction(SIGALRM, &sigact, NULL);
 | 
			
		||||
#else
 | 
			
		||||
    /* no sigaction(), revert to the much lamer signal() */
 | 
			
		||||
#ifdef HAVE_SIGNAL
 | 
			
		||||
    signal(SIGALRM, alarmfunc);
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    /* We set the timeout on the name resolving phase first, separately from
 | 
			
		||||
     * the download/upload part to allow a maximum time on everything. This is
 | 
			
		||||
     * a signal-based timeout, why it won't work and shouldn't be used in
 | 
			
		||||
     * multi-threaded environments. */
 | 
			
		||||
 | 
			
		||||
    /* myalarm() makes a signal get sent when the timeout fires off, and that
 | 
			
		||||
#ifdef HAVE_ALARM
 | 
			
		||||
    /* alarm() makes a signal get sent when the timeout fires off, and that
 | 
			
		||||
       will abort system calls */
 | 
			
		||||
    if(data->set.connecttimeout)
 | 
			
		||||
      myalarm(data->set.connecttimeout);
 | 
			
		||||
    else
 | 
			
		||||
      myalarm(data->set.timeout);
 | 
			
		||||
    prev_alarm = alarm(data->set.connecttimeout?
 | 
			
		||||
                       data->set.connecttimeout:
 | 
			
		||||
                       data->set.timeout);
 | 
			
		||||
    /* We can expect the conn->created time to be "now", as that was just
 | 
			
		||||
       recently set in the beginning of this function and nothing slow
 | 
			
		||||
       has been done since then until now. */
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /*************************************************************
 | 
			
		||||
@@ -1966,7 +1977,8 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 | 
			
		||||
    }
 | 
			
		||||
    if(!conn->hostaddr) {
 | 
			
		||||
      failf(data, "Couldn't resolve host '%s'", conn->name);
 | 
			
		||||
      return CURLE_COULDNT_RESOLVE_HOST;
 | 
			
		||||
      result =  CURLE_COULDNT_RESOLVE_HOST;
 | 
			
		||||
      /* don't return yet, we need to clean up the timeout first */
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  else if(!conn->hostaddr) {
 | 
			
		||||
@@ -1980,13 +1992,47 @@ static CURLcode CreateConnection(struct SessionHandle *data,
 | 
			
		||||
 | 
			
		||||
    if(!conn->hostaddr) {
 | 
			
		||||
      failf(data, "Couldn't resolve proxy '%s'", conn->proxyhost);
 | 
			
		||||
      return CURLE_COULDNT_RESOLVE_PROXY;
 | 
			
		||||
      result = CURLE_COULDNT_RESOLVE_PROXY;
 | 
			
		||||
      /* don't return yet, we need to clean up the timeout first */
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  Curl_pgrsTime(data, TIMER_NAMELOOKUP);
 | 
			
		||||
  if(data->set.timeout || data->set.connecttimeout)
 | 
			
		||||
    /* switch off signal-based timeouts */
 | 
			
		||||
    myalarm(0);
 | 
			
		||||
#ifdef HAVE_ALARM
 | 
			
		||||
  if(data->set.timeout || data->set.connecttimeout) {
 | 
			
		||||
#ifdef HAVE_SIGACTION
 | 
			
		||||
    if(keep_copysig) {
 | 
			
		||||
      /* we got a struct as it looked before, now put that one back nice
 | 
			
		||||
         and clean */
 | 
			
		||||
      sigaction(SIGALRM, &keep_sigact, NULL); /* put it back */
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    /* switch back the alarm() to either zero or to what it was before minus
 | 
			
		||||
       the time we spent until now! */
 | 
			
		||||
    if(prev_alarm) {
 | 
			
		||||
      /* there was an alarm() set before us, now put it back */
 | 
			
		||||
      long elapsed_ms = Curl_tvdiff(Curl_tvnow(), conn->created);
 | 
			
		||||
      long alarm_set;
 | 
			
		||||
 | 
			
		||||
      /* the alarm period is counted in even number of seconds */
 | 
			
		||||
      alarm_set = prev_alarm - elapsed_ms/1000;
 | 
			
		||||
 | 
			
		||||
      if(alarm_set<=0) {
 | 
			
		||||
        /* if it turned negative, we should fire off a SIGALRM here, but we
 | 
			
		||||
           won't, and zero would be to switch it off so we never set it to
 | 
			
		||||
           less than 1! */
 | 
			
		||||
        alarm(1);
 | 
			
		||||
        result = CURLE_OPERATION_TIMEOUTED;
 | 
			
		||||
        failf(data, "Previous alarm fired off!");
 | 
			
		||||
      }
 | 
			
		||||
      else
 | 
			
		||||
        alarm(alarm_set);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
      alarm(0); /* just shut it off */
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  if(result)
 | 
			
		||||
    return result;
 | 
			
		||||
 | 
			
		||||
  /*************************************************************
 | 
			
		||||
   * Proxy authentication
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user