X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=libfcgi%2Fos_unix.c;h=6d7dc534a01636cad3afb89c866eef3fa02def74;hb=cfcd1f2cbda79cfce5589d6c835b9bdced092197;hp=b43664aa0e37a22fc5f6df0f2d498518518ccb20;hpb=226e4c76ecde6a023b9a0f0495d845ad31894f3b;p=catagits%2Ffcgi2.git diff --git a/libfcgi/os_unix.c b/libfcgi/os_unix.c index b43664a..6d7dc53 100755 --- a/libfcgi/os_unix.c +++ b/libfcgi/os_unix.c @@ -17,7 +17,7 @@ */ #ifndef lint -static const char rcsid[] = "$Id: os_unix.c,v 1.20 2000/09/20 15:45:29 robs Exp $"; +static const char rcsid[] = "$Id: os_unix.c,v 1.38 2003/06/22 00:16:43 robs Exp $"; #endif /* not lint */ #include "fcgi_config.h" @@ -41,6 +41,7 @@ static const char rcsid[] = "$Id: os_unix.c,v 1.20 2000/09/20 15:45:29 robs Exp #include #include #include +#include #ifdef HAVE_NETDB_H #include @@ -55,17 +56,11 @@ static const char rcsid[] = "$Id: os_unix.c,v 1.20 2000/09/20 15:45:29 robs Exp #endif #include "fastcgi.h" -#include "fcgiapp.h" -#include "fcgiappmisc.h" #include "fcgimisc.h" #include "fcgios.h" -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 +#ifndef INADDR_NONE +#define INADDR_NONE ((unsigned long) -1) #endif /* @@ -105,7 +100,50 @@ static fd_set writeFdSetPost; static int numWrPosted = 0; static int volatile maxFd = -1; - +static int shutdownPending = FALSE; +static int shutdownNow = FALSE; + +void OS_ShutdownPending() +{ + shutdownPending = TRUE; +} + +static void OS_Sigusr1Handler(int signo) +{ + OS_ShutdownPending(); +} + +static void OS_SigpipeHandler(int signo) +{ + ; +} + +static void installSignalHandler(int signo, const struct sigaction * act, int force) +{ + struct sigaction sa; + + sigaction(signo, NULL, &sa); + + if (force || sa.sa_handler == SIG_DFL) + { + sigaction(signo, act, NULL); + } +} + +static void OS_InstallSignalHandlers(int force) +{ + struct sigaction sa; + + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + + sa.sa_handler = OS_SigpipeHandler; + installSignalHandler(SIGPIPE, &sa, force); + + sa.sa_handler = OS_Sigusr1Handler; + installSignalHandler(SIGUSR1, &sa, force); +} + /* *-------------------------------------------------------------- * @@ -142,11 +180,14 @@ int OS_LibInit(int stdioFds[3]) FD_ZERO(&writeFdSet); FD_ZERO(&readFdSetPost); FD_ZERO(&writeFdSetPost); + + OS_InstallSignalHandlers(FALSE); + libInitialized = TRUE; + return 0; } - /* *-------------------------------------------------------------- * @@ -173,7 +214,6 @@ void OS_LibShutdown() return; } - /* *---------------------------------------------------------------------- * @@ -220,13 +260,11 @@ static int OS_BuildSockAddrUn(const char *bindPath, #endif return 0; } - union SockAddrUnion { struct sockaddr_un unixVariant; struct sockaddr_in inetVariant; }; - /* * OS_CreateLocalIpcFd -- * @@ -247,10 +285,11 @@ union SockAddrUnion { int OS_CreateLocalIpcFd(const char *bindPath, int backlog) { int listenSock, servLen; - union SockAddrUnion sa; + union SockAddrUnion sa; int tcp = FALSE; + unsigned long tcp_ia = 0; char *tp; - short port; + short port = 0; char host[MAXPATHLEN]; strcpy(host, bindPath); @@ -262,12 +301,26 @@ int OS_CreateLocalIpcFd(const char *bindPath, int backlog) tcp = TRUE; } } - if(tcp && (*host && strcmp(host, "localhost") != 0)) { - fprintf(stderr, "To start a service on a TCP port can not " - "specify a host name.\n" - "You should either use \"localhost:\" or " - " just use \":.\"\n"); - exit(1); + if(tcp) { + if (!*host || !strcmp(host,"*")) { + tcp_ia = htonl(INADDR_ANY); + } else { + tcp_ia = inet_addr(host); + if (tcp_ia == INADDR_NONE) { + struct hostent * hep; + hep = gethostbyname(host); + if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) { + fprintf(stderr, "Cannot resolve host name %s -- exiting!\n", host); + exit(1); + } + if (hep->h_addr_list[1]) { + fprintf(stderr, "Host %s has multiple addresses ---\n", host); + fprintf(stderr, "you must choose one explicitly!!!\n"); + exit(1); + } + tcp_ia = ((struct in_addr *) (hep->h_addr))->s_addr; + } + } } if(tcp) { @@ -293,7 +346,7 @@ int OS_CreateLocalIpcFd(const char *bindPath, int backlog) if(tcp) { memset((char *) &sa.inetVariant, 0, sizeof(sa.inetVariant)); sa.inetVariant.sin_family = AF_INET; - sa.inetVariant.sin_addr.s_addr = htonl(INADDR_ANY); + sa.inetVariant.sin_addr.s_addr = tcp_ia; sa.inetVariant.sin_port = htons(port); servLen = sizeof(sa.inetVariant); } else { @@ -312,7 +365,6 @@ int OS_CreateLocalIpcFd(const char *bindPath, int backlog) return listenSock; } - /* *---------------------------------------------------------------------- * @@ -340,7 +392,7 @@ int OS_FcgiConnect(char *bindPath) int connectStatus; char *tp; char host[MAXPATHLEN]; - short port; + short port = 0; int tcp = FALSE; strcpy(host, bindPath); @@ -386,7 +438,6 @@ int OS_FcgiConnect(char *bindPath) } } - /* *-------------------------------------------------------------- * @@ -405,9 +456,10 @@ int OS_FcgiConnect(char *bindPath) */ int OS_Read(int fd, char * buf, size_t len) { + if (shutdownNow) return -1; return(read(fd, buf, len)); } - + /* *-------------------------------------------------------------- * @@ -426,10 +478,10 @@ int OS_Read(int fd, char * buf, size_t len) */ int OS_Write(int fd, char * buf, size_t len) { + if (shutdownNow) return -1; return(write(fd, buf, len)); } - /* *---------------------------------------------------------------------- * @@ -495,7 +547,6 @@ int OS_SpawnChild(char *appPath, int listenFd) return 0; } - /* *-------------------------------------------------------------- * @@ -552,7 +603,6 @@ static void GrowAsyncTable(void) } - /* *-------------------------------------------------------------- * @@ -588,7 +638,7 @@ int OS_AsyncRead(int fd, int offset, void *buf, int len, if(fd > maxFd) maxFd = fd; - if(index >= asyncIoTableSize) { + while (index >= asyncIoTableSize) { GrowAsyncTable(); } @@ -603,7 +653,7 @@ int OS_AsyncRead(int fd, int offset, void *buf, int len, FD_SET(fd, &readFdSet); return 0; } - + /* *-------------------------------------------------------------- * @@ -637,7 +687,7 @@ int OS_AsyncWrite(int fd, int offset, void *buf, int len, if(fd > maxFd) maxFd = fd; - if(index >= asyncIoTableSize) { + while (index >= asyncIoTableSize) { GrowAsyncTable(); } @@ -652,7 +702,7 @@ int OS_AsyncWrite(int fd, int offset, void *buf, int len, FD_SET(fd, &writeFdSet); return 0; } - + /* *-------------------------------------------------------------- * @@ -669,8 +719,11 @@ int OS_AsyncWrite(int fd, int offset, void *buf, int len, * *-------------------------------------------------------------- */ -int OS_Close(int fd) +int OS_Close(int fd, int shutdown_ok) { + if (fd == -1) + return 0; + if (asyncIoInUse) { int index = AIO_RD_IX(fd); @@ -691,9 +744,40 @@ int OS_Close(int fd) maxFd--; } } + + /* + * shutdown() the send side and then read() from client until EOF + * or a timeout expires. This is done to minimize the potential + * that a TCP RST will be sent by our TCP stack in response to + * receipt of additional data from the client. The RST would + * cause the client to discard potentially useful response data. + */ + + if (shutdown_ok) + { + if (shutdown(fd, 1) == 0) + { + struct timeval tv; + fd_set rfds; + int rv; + char trash[1024]; + + FD_ZERO(&rfds); + + do + { + FD_SET(fd, &rfds); + tv.tv_sec = 2; + tv.tv_usec = 0; + rv = select(fd + 1, &rfds, NULL, NULL, &tv); + } + while (rv > 0 && read(fd, trash, sizeof(trash)) > 0); + } + } + return close(fd); } - + /* *-------------------------------------------------------------- * @@ -718,7 +802,6 @@ int OS_CloseRead(int fd) return shutdown(fd, 0); } - /* *-------------------------------------------------------------- * @@ -839,7 +922,7 @@ int OS_DoIo(struct timeval *tmo) * Not all systems have strdup(). * @@@ autoconf should determine whether or not this is needed, but for now.. */ -char * str_dup(const char * str) +static char * str_dup(const char * str) { char * sdup = (char *) malloc(strlen(str) + 1); @@ -849,7 +932,6 @@ char * str_dup(const char * str) return sdup; } - /* *---------------------------------------------------------------------- * @@ -889,7 +971,6 @@ static int ClientAddrOK(struct sockaddr_in *saPtr, const char *clientList) return result; } - /* *---------------------------------------------------------------------- * @@ -920,7 +1001,9 @@ static int AcquireLock(int sock, int fail_on_intr) if (fcntl(sock, F_SETLKW, &lock) != -1) return 0; - } while (errno == EINTR && !fail_on_intr); + } while (errno == EINTR + && ! fail_on_intr + && ! shutdownPending); return -1; @@ -928,7 +1011,7 @@ static int AcquireLock(int sock, int fail_on_intr) return 0; #endif } - + /* *---------------------------------------------------------------------- * @@ -967,7 +1050,6 @@ static int ReleaseLock(int sock) #endif } - /********************************************************************** * Determine if the errno resulting from a failed accept() warrants a * retry or exit(). Based on Apache's http_main.c accept() handling @@ -1064,7 +1146,7 @@ static int is_af_unix_keeper(const int fd) */ int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) { - int socket; + int socket = -1; union { struct sockaddr_un un; struct sockaddr_in in; @@ -1081,14 +1163,25 @@ int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) #else int len = sizeof(sa); #endif + if (shutdownPending) break; + /* There's a window here */ + socket = accept(listen_sock, (struct sockaddr *)&sa, &len); - } while (socket < 0 && errno == EINTR && !fail_on_intr); + } while (socket < 0 + && errno == EINTR + && ! fail_on_intr + && ! shutdownPending); if (socket < 0) { - if (!is_reasonable_accept_errno(errno)) { + if (shutdownPending || ! is_reasonable_accept_errno(errno)) { int errnoSave = errno; + ReleaseLock(listen_sock); - errno = errnoSave; + + if (! shutdownPending) { + errno = errnoSave; + } + return (-1); } errno = 0; @@ -1123,7 +1216,7 @@ int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) return (socket); } - + /* *---------------------------------------------------------------------- * @@ -1139,12 +1232,11 @@ int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs) * *---------------------------------------------------------------------- */ -int OS_IpcClose(int ipcFd) +int OS_IpcClose(int ipcFd, int shutdown) { - return OS_Close(ipcFd); + return OS_Close(ipcFd, shutdown); } - /* *---------------------------------------------------------------------- * @@ -1172,6 +1264,8 @@ int OS_IsFcgi(int sock) int len = sizeof(sa); #endif + errno = 0; + if (getpeername(sock, (struct sockaddr *)&sa, &len) != 0 && errno == ENOTCONN) { return TRUE; } @@ -1179,7 +1273,7 @@ int OS_IsFcgi(int sock) return FALSE; } } - + /* *---------------------------------------------------------------------- *