mirror of
https://github.com/moparisthebest/curl
synced 2024-08-13 17:03:50 -04:00
signal handling to cleanup on SIGINT and SIGTERM
This commit is contained in:
parent
8b49428298
commit
fba233bb34
@ -183,17 +183,117 @@ static const char *doc404 = "HTTP/1.1 404 Not Found\r\n"
|
|||||||
"The requested URL was not found on this server.\n"
|
"The requested URL was not found on this server.\n"
|
||||||
"<P><HR><ADDRESS>" SWSVERSION "</ADDRESS>\n" "</BODY></HTML>\n";
|
"<P><HR><ADDRESS>" SWSVERSION "</ADDRESS>\n" "</BODY></HTML>\n";
|
||||||
|
|
||||||
#ifndef WIN32
|
/* do-nothing macro replacement for systems which lack siginterrupt() */
|
||||||
# if defined(SIGPIPE) && defined(HAVE_SIGNAL)
|
|
||||||
static volatile int sigpipe; /* Why? It's not used */
|
#ifndef HAVE_SIGINTERRUPT
|
||||||
static void sigpipe_handler(int sig)
|
#define siginterrupt(x,y) do {} while(0)
|
||||||
{
|
|
||||||
(void)sig; /* prevent warning */
|
|
||||||
sigpipe = 1;
|
|
||||||
}
|
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* vars used to keep around previous signal handlers */
|
||||||
|
|
||||||
|
typedef RETSIGTYPE (*SIGHANDLER_T)(int);
|
||||||
|
|
||||||
|
#ifdef SIGHUP
|
||||||
|
static SIGHANDLER_T old_sighup_handler = SIG_ERR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
static SIGHANDLER_T old_sigpipe_handler = SIG_ERR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGALRM
|
||||||
|
static SIGHANDLER_T old_sigalrm_handler = SIG_ERR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGINT
|
||||||
|
static SIGHANDLER_T old_sigint_handler = SIG_ERR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SIGTERM
|
||||||
|
static SIGHANDLER_T old_sigterm_handler = SIG_ERR;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* var which if set indicates that the program should finish execution */
|
||||||
|
|
||||||
|
SIG_ATOMIC_T got_exit_signal = 0;
|
||||||
|
|
||||||
|
/* if next is set indicates the first signal handled in exit_signal_handler */
|
||||||
|
|
||||||
|
static volatile int exit_signal = 0;
|
||||||
|
|
||||||
|
/* signal handler that will be triggered to indicate that the program
|
||||||
|
should finish its execution in a controlled manner as soon as possible.
|
||||||
|
The first time this is called it will set got_exit_signal to one and
|
||||||
|
store in exit_signal the signal that triggered its execution. */
|
||||||
|
|
||||||
|
static RETSIGTYPE exit_signal_handler(int signum)
|
||||||
|
{
|
||||||
|
int old_errno = ERRNO;
|
||||||
|
if(got_exit_signal == 0) {
|
||||||
|
got_exit_signal = 1;
|
||||||
|
exit_signal = signum;
|
||||||
|
}
|
||||||
|
(void)signal(signum, exit_signal_handler);
|
||||||
|
SET_ERRNO(old_errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void install_signal_handlers(void)
|
||||||
|
{
|
||||||
|
#ifdef SIGHUP
|
||||||
|
/* ignore SIGHUP signal */
|
||||||
|
if((old_sighup_handler = signal(SIGHUP, SIG_IGN)) == SIG_ERR)
|
||||||
|
logmsg("cannot install SIGHUP handler: %s", strerror(ERRNO));
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
/* ignore SIGPIPE signal */
|
||||||
|
if((old_sigpipe_handler = signal(SIGPIPE, SIG_IGN)) == SIG_ERR)
|
||||||
|
logmsg("cannot install SIGPIPE handler: %s", strerror(ERRNO));
|
||||||
|
#endif
|
||||||
|
#ifdef SIGALRM
|
||||||
|
/* ignore SIGALRM signal */
|
||||||
|
if((old_sigalrm_handler = signal(SIGALRM, SIG_IGN)) == SIG_ERR)
|
||||||
|
logmsg("cannot install SIGALRM handler: %s", strerror(ERRNO));
|
||||||
|
#endif
|
||||||
|
#ifdef SIGINT
|
||||||
|
/* handle SIGINT signal with our exit_signal_handler */
|
||||||
|
if((old_sigint_handler = signal(SIGINT, exit_signal_handler)) == SIG_ERR)
|
||||||
|
logmsg("cannot install SIGINT handler: %s", strerror(ERRNO));
|
||||||
|
else
|
||||||
|
siginterrupt(SIGINT, 1);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTERM
|
||||||
|
/* handle SIGTERM signal with our exit_signal_handler */
|
||||||
|
if((old_sigterm_handler = signal(SIGTERM, exit_signal_handler)) == SIG_ERR)
|
||||||
|
logmsg("cannot install SIGTERM handler: %s", strerror(ERRNO));
|
||||||
|
else
|
||||||
|
siginterrupt(SIGTERM, 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static void restore_signal_handlers(void)
|
||||||
|
{
|
||||||
|
#ifdef SIGHUP
|
||||||
|
if(SIG_ERR != old_sighup_handler)
|
||||||
|
(void)signal(SIGHUP, old_sighup_handler);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGPIPE
|
||||||
|
if(SIG_ERR != old_sigpipe_handler)
|
||||||
|
(void)signal(SIGPIPE, old_sigpipe_handler);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGALRM
|
||||||
|
if(SIG_ERR != old_sigalrm_handler)
|
||||||
|
(void)signal(SIGALRM, old_sigalrm_handler);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGINT
|
||||||
|
if(SIG_ERR != old_sigint_handler)
|
||||||
|
(void)signal(SIGINT, old_sigint_handler);
|
||||||
|
#endif
|
||||||
|
#ifdef SIGTERM
|
||||||
|
if(SIG_ERR != old_sigterm_handler)
|
||||||
|
(void)signal(SIGTERM, old_sigterm_handler);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static int ProcessRequest(struct httprequest *req)
|
static int ProcessRequest(struct httprequest *req)
|
||||||
{
|
{
|
||||||
char *line=&req->reqbuf[req->checkindex];
|
char *line=&req->reqbuf[req->checkindex];
|
||||||
@ -525,6 +625,10 @@ static void storerequest(char *reqbuf, ssize_t totalsize)
|
|||||||
do {
|
do {
|
||||||
written = (ssize_t)fwrite((void *) &reqbuf[totalsize-writeleft],
|
written = (ssize_t)fwrite((void *) &reqbuf[totalsize-writeleft],
|
||||||
1, (size_t)writeleft, dump);
|
1, (size_t)writeleft, dump);
|
||||||
|
if(got_exit_signal) {
|
||||||
|
res = fclose(dump);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (written > 0)
|
if (written > 0)
|
||||||
writeleft -= written;
|
writeleft -= written;
|
||||||
} while ((writeleft > 0) && ((error = ERRNO) == EINTR));
|
} while ((writeleft > 0) && ((error = ERRNO) == EINTR));
|
||||||
@ -598,6 +702,8 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
|
|||||||
else
|
else
|
||||||
got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
|
got = sread(sock, reqbuf + req->offset, REQBUFSIZ-1 - req->offset);
|
||||||
}
|
}
|
||||||
|
if(got_exit_signal)
|
||||||
|
return 1;
|
||||||
if (got <= 0) {
|
if (got <= 0) {
|
||||||
if (got < 0) {
|
if (got < 0) {
|
||||||
logmsg("recv() returned error: %d", SOCKERRNO);
|
logmsg("recv() returned error: %d", SOCKERRNO);
|
||||||
@ -643,6 +749,9 @@ static int get_request(curl_socket_t sock, struct httprequest *req)
|
|||||||
/* dump the request to an external file */
|
/* dump the request to an external file */
|
||||||
storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
|
storerequest(reqbuf, req->pipelining ? req->checkindex : req->offset);
|
||||||
|
|
||||||
|
if(got_exit_signal)
|
||||||
|
return 1;
|
||||||
|
|
||||||
return fail; /* return 0 on success */
|
return fail; /* return 0 on success */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -678,6 +787,8 @@ static int send_doc(curl_socket_t sock, struct httprequest *req)
|
|||||||
count = strlen(STREAMTHIS);
|
count = strlen(STREAMTHIS);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
written = swrite(sock, STREAMTHIS, count);
|
written = swrite(sock, STREAMTHIS, count);
|
||||||
|
if(got_exit_signal)
|
||||||
|
break;
|
||||||
if(written != (ssize_t)count) {
|
if(written != (ssize_t)count) {
|
||||||
logmsg("Stopped streaming");
|
logmsg("Stopped streaming");
|
||||||
break;
|
break;
|
||||||
@ -877,6 +988,7 @@ int main(int argc, char *argv[])
|
|||||||
#endif /* ENABLE_IPV6 */
|
#endif /* ENABLE_IPV6 */
|
||||||
curl_socket_t sock = CURL_SOCKET_BAD;
|
curl_socket_t sock = CURL_SOCKET_BAD;
|
||||||
curl_socket_t msgsock = CURL_SOCKET_BAD;
|
curl_socket_t msgsock = CURL_SOCKET_BAD;
|
||||||
|
int wrotepidfile = 0;
|
||||||
int flag;
|
int flag;
|
||||||
unsigned short port = DEFAULT_PORT;
|
unsigned short port = DEFAULT_PORT;
|
||||||
char *pidname= (char *)".http.pid";
|
char *pidname= (char *)".http.pid";
|
||||||
@ -935,17 +1047,9 @@ int main(int argc, char *argv[])
|
|||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
win32_init();
|
win32_init();
|
||||||
atexit(win32_cleanup);
|
atexit(win32_cleanup);
|
||||||
#else
|
#endif
|
||||||
|
|
||||||
#ifdef SIGPIPE
|
install_signal_handlers();
|
||||||
#ifdef HAVE_SIGNAL
|
|
||||||
signal(SIGPIPE, sigpipe_handler);
|
|
||||||
#endif
|
|
||||||
#ifdef HAVE_SIGINTERRUPT
|
|
||||||
siginterrupt(SIGPIPE, 1);
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
if(!use_ipv6)
|
if(!use_ipv6)
|
||||||
@ -960,7 +1064,7 @@ int main(int argc, char *argv[])
|
|||||||
error = SOCKERRNO;
|
error = SOCKERRNO;
|
||||||
logmsg("Error creating socket: (%d) %s",
|
logmsg("Error creating socket: (%d) %s",
|
||||||
error, strerror(error));
|
error, strerror(error));
|
||||||
return 1;
|
goto sws_cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
flag = 1;
|
flag = 1;
|
||||||
@ -969,8 +1073,7 @@ int main(int argc, char *argv[])
|
|||||||
error = SOCKERRNO;
|
error = SOCKERRNO;
|
||||||
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
|
logmsg("setsockopt(SO_REUSEADDR) failed with error: (%d) %s",
|
||||||
error, strerror(error));
|
error, strerror(error));
|
||||||
sclose(sock);
|
goto sws_cleanup;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_IPV6
|
#ifdef ENABLE_IPV6
|
||||||
@ -995,13 +1098,7 @@ int main(int argc, char *argv[])
|
|||||||
error = SOCKERRNO;
|
error = SOCKERRNO;
|
||||||
logmsg("Error binding socket on port %hu: (%d) %s",
|
logmsg("Error binding socket on port %hu: (%d) %s",
|
||||||
port, error, strerror(error));
|
port, error, strerror(error));
|
||||||
sclose(sock);
|
goto sws_cleanup;
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!write_pidfile(pidname)) {
|
|
||||||
sclose(sock);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
logmsg("Running %s version on port %d", ipv_inuse, (int)port);
|
logmsg("Running %s version on port %d", ipv_inuse, (int)port);
|
||||||
@ -1012,13 +1109,18 @@ int main(int argc, char *argv[])
|
|||||||
error = SOCKERRNO;
|
error = SOCKERRNO;
|
||||||
logmsg("listen() failed with error: (%d) %s",
|
logmsg("listen() failed with error: (%d) %s",
|
||||||
error, strerror(error));
|
error, strerror(error));
|
||||||
sclose(sock);
|
goto sws_cleanup;
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wrotepidfile = write_pidfile(pidname);
|
||||||
|
if(!wrotepidfile)
|
||||||
|
goto sws_cleanup;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
msgsock = accept(sock, NULL, NULL);
|
msgsock = accept(sock, NULL, NULL);
|
||||||
|
|
||||||
|
if(got_exit_signal)
|
||||||
|
break;
|
||||||
if (CURL_SOCKET_BAD == msgsock) {
|
if (CURL_SOCKET_BAD == msgsock) {
|
||||||
error = SOCKERRNO;
|
error = SOCKERRNO;
|
||||||
logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
|
logmsg("MAJOR ERROR: accept() failed with error: (%d) %s",
|
||||||
@ -1066,6 +1168,9 @@ int main(int argc, char *argv[])
|
|||||||
req.pipelining = FALSE;
|
req.pipelining = FALSE;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
if(got_exit_signal)
|
||||||
|
break;
|
||||||
|
|
||||||
if(get_request(msgsock, &req))
|
if(get_request(msgsock, &req))
|
||||||
/* non-zero means error, break out of loop */
|
/* non-zero means error, break out of loop */
|
||||||
break;
|
break;
|
||||||
@ -1086,6 +1191,9 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
send_doc(msgsock, &req);
|
send_doc(msgsock, &req);
|
||||||
|
|
||||||
|
if(got_exit_signal)
|
||||||
|
break;
|
||||||
|
|
||||||
if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) {
|
if((req.testno < 0) && (req.testno != DOCNUMBER_CONNECT)) {
|
||||||
logmsg("special request received, no persistency");
|
logmsg("special request received, no persistency");
|
||||||
break;
|
break;
|
||||||
@ -1100,8 +1208,12 @@ int main(int argc, char *argv[])
|
|||||||
/* if we got a CONNECT, loop and get another request as well! */
|
/* if we got a CONNECT, loop and get another request as well! */
|
||||||
} while(req.open || (req.testno == DOCNUMBER_CONNECT));
|
} while(req.open || (req.testno == DOCNUMBER_CONNECT));
|
||||||
|
|
||||||
|
if(got_exit_signal)
|
||||||
|
break;
|
||||||
|
|
||||||
logmsg("====> Client disconnect");
|
logmsg("====> Client disconnect");
|
||||||
sclose(msgsock);
|
sclose(msgsock);
|
||||||
|
msgsock = CURL_SOCKET_BAD;
|
||||||
|
|
||||||
clear_advisor_read_lock(SERVERLOGS_LOCK);
|
clear_advisor_read_lock(SERVERLOGS_LOCK);
|
||||||
|
|
||||||
@ -1112,10 +1224,35 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
sclose(sock);
|
sws_cleanup:
|
||||||
|
|
||||||
|
if((msgsock != sock) && (msgsock != CURL_SOCKET_BAD))
|
||||||
|
sclose(msgsock);
|
||||||
|
|
||||||
|
if(sock != CURL_SOCKET_BAD)
|
||||||
|
sclose(sock);
|
||||||
|
|
||||||
|
if(got_exit_signal)
|
||||||
|
logmsg("signalled to die");
|
||||||
|
|
||||||
|
if(wrotepidfile)
|
||||||
|
unlink(pidname);
|
||||||
|
|
||||||
clear_advisor_read_lock(SERVERLOGS_LOCK);
|
clear_advisor_read_lock(SERVERLOGS_LOCK);
|
||||||
|
|
||||||
|
restore_signal_handlers();
|
||||||
|
|
||||||
|
if(got_exit_signal) {
|
||||||
|
logmsg("========> sws exits with signal (%d)", exit_signal);
|
||||||
|
/*
|
||||||
|
* To properly set the return status of the process we
|
||||||
|
* must raise the same signal SIGINT or SIGTERM that we
|
||||||
|
* caught and let the old handler take care of it.
|
||||||
|
*/
|
||||||
|
raise(exit_signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
logmsg("========> sws quits");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user