mirror of
https://github.com/curl/curl.git
synced 2025-01-18 14:04:30 +08:00
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:
parent
3dfc509d33
commit
2e32d415c0
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user