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:
Daniel Stenberg 2001-11-06 19:33:13 +00:00
parent 3dfc509d33
commit 2e32d415c0
3 changed files with 82 additions and 40 deletions

View File

@ -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 "/"

View File

@ -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
View File

@ -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