diff -ur --exclude=debian curl-7.9.1/lib/setup.h curl-ssl-7.9.1/lib/setup.h --- curl-7.9.1/lib/setup.h Fri Nov 2 14:04:23 2001 +++ curl-ssl-7.9.1/lib/setup.h Thu Nov 15 13:15:12 2001 @@ -110,13 +110,13 @@ #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 @@ #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 "/" diff -ur --exclude=debian curl-7.9.1/lib/transfer.c curl-ssl-7.9.1/lib/transfer.c --- curl-7.9.1/lib/transfer.c Sat Nov 3 00:09:39 2001 +++ curl-ssl-7.9.1/lib/transfer.c Thu Nov 15 13:15:12 2001 @@ -1159,10 +1159,6 @@ if(newurl) free(newurl); - /* make absolutely sure the alarm is switched off! */ - if(data->set.timeout || data->set.connecttimeout) - myalarm(0); - return res; } diff -ur --exclude=debian curl-7.9.1/lib/url.c curl-ssl-7.9.1/lib/url.c --- curl-7.9.1/lib/url.c Thu Nov 1 14:54:32 2001 +++ curl-ssl-7.9.1/lib/url.c Thu Nov 15 13:15:12 2001 @@ -72,7 +72,6 @@ #include #endif - #ifndef HAVE_SELECT #error "We can't compile without select() support!" #endif @@ -200,10 +199,6 @@ { /* 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) @@ -264,24 +259,6 @@ *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 *************************************************************/ #if defined(HAVE_SIGNAL) && defined(SIGPIPE) @@ -1170,6 +1147,14 @@ 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,44 @@ * 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); + keep_sigact = 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 +1978,8 @@ } 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 +1993,47 @@ 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