sas Sun Sep 21 18:08:18 2003 EDT Modified files: (Branch: PHP_4_3) /php-src/sapi/cgi cgi_main.c /php-src/sapi/cgi/libfcgi fcgiapp.c os_unix.c os_win32.c /php-src/sapi/cgi/libfcgi/include fastcgi.h fcgi_config_win32.h fcgi_stdio.h fcgiapp.h fcgimisc.h fcgio.h fcgios.h Log: Major bug fix upgrade to the bundled libfcgi A delta between libfcgi 2.2.2 and 2.4.1-SNAP has been applied to the source. Shane's impersonation, putenv and exit->return improvements have been carried over. One of Shane's changes caused the first process to hang after one request. The modification has been deactived (os_win32.c). These changes together with a patch to mod_fastcgi, make Apache/mod_fastcgi and PHP work under Win32. It was basically unusable before that.
Index: php-src/sapi/cgi/cgi_main.c diff -u php-src/sapi/cgi/cgi_main.c:1.190.2.48 php-src/sapi/cgi/cgi_main.c:1.190.2.49 --- php-src/sapi/cgi/cgi_main.c:1.190.2.48 Wed Sep 3 04:14:14 2003 +++ php-src/sapi/cgi/cgi_main.c Sun Sep 21 18:08:13 2003 @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: cgi_main.c,v 1.190.2.48 2003/09/03 08:14:14 sas Exp $ */ +/* $Id: cgi_main.c,v 1.190.2.49 2003/09/21 22:08:13 sas Exp $ */ #include "php.h" #include "php_globals.h" @@ -218,13 +218,8 @@ #define STDOUT_FILENO 1 #endif -static inline size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC) +static size_t sapi_cgibin_single_write(const char *str, uint str_length TSRMLS_DC) { -#ifdef PHP_WRITE_STDOUT - long ret; -#else - size_t ret; -#endif #if PHP_FASTCGI if (!FCGX_IsCGI()) { @@ -236,13 +231,22 @@ return ret; } #endif + #ifdef PHP_WRITE_STDOUT - ret = write(STDOUT_FILENO, str, str_length); - if (ret <= 0) return 0; - return ret; + { + long ret; + + ret = write(STDOUT_FILENO, str, str_length); + if (ret <= 0) return 0; + return ret; + } #else - ret = fwrite(str, 1, MIN(str_length, 16384), stdout); - return ret; + { + size_t ret; + + ret = fwrite(str, 1, MIN(str_length, 16384), stdout); + return ret; + } #endif } Index: php-src/sapi/cgi/libfcgi/fcgiapp.c diff -u php-src/sapi/cgi/libfcgi/fcgiapp.c:1.1.4.1 php-src/sapi/cgi/libfcgi/fcgiapp.c:1.1.4.2 --- php-src/sapi/cgi/libfcgi/fcgiapp.c:1.1.4.1 Sun Dec 1 18:11:14 2002 +++ php-src/sapi/cgi/libfcgi/fcgiapp.c Sun Sep 21 18:08:16 2003 @@ -11,7 +11,7 @@ * */ #ifndef lint -static const char rcsid[] = "$Id: fcgiapp.c,v 1.1.4.1 2002/12/01 23:11:14 shane Exp $"; +static const char rcsid[] = "$Id: fcgiapp.c,v 1.1.4.2 2003/09/21 22:08:16 sas Exp $"; #endif /* not lint */ #include <assert.h> @@ -70,7 +70,6 @@ static int isFastCGI = -1; static char *webServerAddressList = NULL; static FCGX_Request the_request; -void _FCGX_FreeStream(FCGX_Stream **streamPtr, int freeData); void FCGX_ShutdownPending(void) { @@ -108,14 +107,20 @@ */ int FCGX_GetChar(FCGX_Stream *stream) { - if(stream->rdNext != stream->stop) - return *stream->rdNext++; - if(stream->isClosed || !stream->isReader) + if (stream->isClosed || ! stream->isReader) return EOF; + + if (stream->rdNext != stream->stop) + return *stream->rdNext++; + stream->fillBuffProc(stream); + if (stream->isClosed) + return EOF; + stream->stopUnget = stream->rdNext; - if(stream->rdNext != stream->stop) + if (stream->rdNext != stream->stop) return *stream->rdNext++; + ASSERT(stream->isClosed); /* bug in fillBufProc if not */ return EOF; } @@ -139,7 +144,7 @@ { int m, bytesMoved; - if(n <= 0) { + if (stream->isClosed || ! stream->isReader || n <= 0) { return 0; } /* @@ -164,10 +169,13 @@ if(bytesMoved == n) return bytesMoved; str += m; - } + } if(stream->isClosed || !stream->isReader) return bytesMoved; stream->fillBuffProc(stream); + if (stream->isClosed) + return bytesMoved; + stream->stopUnget = stream->rdNext; } } @@ -938,8 +946,9 @@ */ if(stream->FCGI_errno == 0) { stream->FCGI_errno = FCGI_errno; - stream->isClosed = TRUE; } + + stream->isClosed = TRUE; } /* @@ -980,7 +989,18 @@ */ } +/* + * A vector of pointers representing the parameters received + * by a FastCGI application server, with the vector's length + * and last valid element so adding new parameters is efficient. + */ +typedef struct Params { + FCGX_ParamArray vec; /* vector of strings */ + int length; /* number of string vec can hold */ + char **cur; /* current item in vec; *cur == NULL */ +} Params; +typedef Params *ParamsPtr; /* *---------------------------------------------------------------------- @@ -1826,18 +1846,12 @@ */ void FCGX_FreeStream(FCGX_Stream **streamPtr) { - _FCGX_FreeStream(streamPtr, TRUE); -} - -void _FCGX_FreeStream(FCGX_Stream **streamPtr, int freeData) -{ FCGX_Stream *stream = *streamPtr; FCGX_Stream_Data *data; if(stream == NULL) { return; } data = (FCGX_Stream_Data *)stream->data; - if (freeData && data->reqDataPtr) free(data->reqDataPtr); data->reqDataPtr = NULL; free(data->mBuff); free(data); @@ -2038,21 +2052,21 @@ if (request == NULL) return; - _FCGX_FreeStream(&request->in, FALSE); - _FCGX_FreeStream(&request->out, FALSE); - _FCGX_FreeStream(&request->err, FALSE); + FCGX_FreeStream(&request->in); + FCGX_FreeStream(&request->out); + FCGX_FreeStream(&request->err); FreeParams(&request->paramsPtr); - request->envp = NULL; if (close) { - OS_IpcClose(request->ipcFd); + OS_IpcClose(request->ipcFd, ! request->detached); request->ipcFd = -1; + request->detached = 0; } } int FCGX_OpenSocket(const char *path, int backlog) { - int rc = OS_CreateLocalIpcFd(path, backlog, 1); + int rc = OS_CreateLocalIpcFd(path, backlog); if (rc == FCGI_LISTENSOCK_FILENO && isFastCGI == 0) { /* XXX probably need to call OS_LibInit() again for Win */ isFastCGI = 1; @@ -2321,3 +2335,23 @@ data->reqDataPtr->appStatus = status; } + +int +FCGX_Attach(FCGX_Request * r) +{ + r->detached = FALSE; + return 0; +} + + +int +FCGX_Detach(FCGX_Request * r) +{ + if (r->ipcFd <= 0) + { + return -1; + } + + r->detached = TRUE; + return 0; +} Index: php-src/sapi/cgi/libfcgi/os_unix.c diff -u php-src/sapi/cgi/libfcgi/os_unix.c:1.2.2.1 php-src/sapi/cgi/libfcgi/os_unix.c:1.2.2.2 --- php-src/sapi/cgi/libfcgi/os_unix.c:1.2.2.1 Sun Dec 1 18:11:14 2002 +++ php-src/sapi/cgi/libfcgi/os_unix.c Sun Sep 21 18:08:16 2003 @@ -17,7 +17,7 @@ */ #ifndef lint -static const char rcsid[] = "$Id: os_unix.c,v 1.2.2.1 2002/12/01 23:11:14 shane Exp $"; +static const char rcsid[] = "$Id: os_unix.c,v 1.2.2.2 2003/09/21 22:08:16 sas Exp $"; #endif /* not lint */ #include "fcgi_config.h" @@ -283,10 +283,10 @@ * *---------------------------------------------------------------------- */ -int OS_CreateLocalIpcFd(const char *bindPath, int backlog, int bCreateMutex) +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; @@ -639,7 +639,7 @@ if(fd > maxFd) maxFd = fd; - if(index >= asyncIoTableSize) { + while (index >= asyncIoTableSize) { GrowAsyncTable(); } @@ -688,7 +688,7 @@ if(fd > maxFd) maxFd = fd; - if(index >= asyncIoTableSize) { + while (index >= asyncIoTableSize) { GrowAsyncTable(); } @@ -720,7 +720,7 @@ * *-------------------------------------------------------------- */ -int OS_Close(int fd) +int OS_Close(int fd, int shutdown_ok) { if (fd == -1) return 0; @@ -745,6 +745,37 @@ 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); } @@ -1204,9 +1235,9 @@ * *---------------------------------------------------------------------- */ -int OS_IpcClose(int ipcFd) +int OS_IpcClose(int ipcFd, int shutdown) { - return OS_Close(ipcFd); + return OS_Close(ipcFd, shutdown); } /* Index: php-src/sapi/cgi/libfcgi/os_win32.c diff -u php-src/sapi/cgi/libfcgi/os_win32.c:1.6 php-src/sapi/cgi/libfcgi/os_win32.c:1.6.2.1 --- php-src/sapi/cgi/libfcgi/os_win32.c:1.6 Sun Oct 13 03:23:17 2002 +++ php-src/sapi/cgi/libfcgi/os_win32.c Sun Sep 21 18:08:16 2003 @@ -17,7 +17,7 @@ * significantly more enjoyable.) */ #ifndef lint -static const char rcsid[] = "$Id: os_win32.c,v 1.6 2002/10/13 07:23:17 shane Exp $"; +static const char rcsid[] = "$Id: os_win32.c,v 1.6.2.1 2003/09/21 22:08:16 sas Exp $"; #endif /* not lint */ #define WIN32_LEAN_AND_MEAN @@ -27,6 +27,7 @@ #include <assert.h> #include <stdio.h> #include <sys/timeb.h> +#include <process.h> #define DLLAPI __declspec(dllexport) @@ -41,6 +42,8 @@ */ #define ACCEPT_TIMEOUT 1000 +#define MUTEX_VARNAME "_FCGI_MUTEX_" +#define SHUTDOWN_EVENT_NAME "_FCGI_SHUTDOWN_EVENT_" #define LOCALHOST "localhost" static HANDLE hIoCompPort = INVALID_HANDLE_VALUE; @@ -50,6 +53,7 @@ static HANDLE stdioHandles[3] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; +// This is a nail for listening to more than one port.. static HANDLE acceptMutex = INVALID_HANDLE_VALUE; static BOOLEAN shutdownPending = FALSE; @@ -123,7 +127,6 @@ // XXX This should be a DESCRIPTOR static HANDLE hListen = INVALID_HANDLE_VALUE; -static OVERLAPPED listenOverlapped; static BOOLEAN libInitialized = FALSE; /* @@ -221,8 +224,8 @@ * *-------------------------------------------------------------- */ -static void StdinThread(LPDWORD startup){ - +static void StdinThread(void * startup) +{ int doIo = TRUE; unsigned long fd; unsigned long bytesRead; @@ -267,20 +270,31 @@ shutdownPending = TRUE; } -/* XXX Need a shutdown now event */ -static DWORD WINAPI ShutdownRequestThread(LPVOID arg) +static void ShutdownRequestThread(void * arg) { HANDLE shutdownEvent = (HANDLE) arg; + WaitForSingleObject(shutdownEvent, INFINITE); + shutdownPending = TRUE; - // Before an accept() is entered the shutdownPending flag is checked. - // If set, OS_Accept() will return -1. If not, it waits - // on a connection request for one second, checks the flag, & repeats. - // Only one process/thread is allowed to do this at time by - // wrapping the accept() with mutex. - return 0; + + if (listenType == FD_PIPE_SYNC) + { + // Its a hassle to get ConnectNamedPipe to return early, + // so just wack the whole process - yes, this will toast + // any requests in progress, but at least its a clean + // shutdown (its better than TerminateProcess()) + exit(0); + } + + // FD_SOCKET_SYNC: When in Accept(), select() is used to poll + // the shutdownPending flag - yeah this isn't pretty either + // but its only one process doing it if an Accept mutex is used. + // This at least buys no toasted requests. } +/* + */ int OS_SetImpersonate(void) { char *os_name = NULL; @@ -313,7 +327,6 @@ WSADATA wsaData; int err; int fakeFd; - DWORD threadId; char *cLenPtr = NULL; char *val = NULL; @@ -357,23 +370,22 @@ { HANDLE shutdownEvent = (HANDLE) atoi(val); - if (! CreateThread(NULL, 0, ShutdownRequestThread, - shutdownEvent, 0, NULL)) + if (_beginthread(ShutdownRequestThread, 0, shutdownEvent) == -1) { return -1; } } - /* - * If an accept mutex is in the env, save it and remove it. - */ - val = getenv(MUTEX_VARNAME); - if (val != NULL) + if (acceptMutex == INVALID_HANDLE_VALUE) { - acceptMutex = (HANDLE) atoi(val); + /* If an accept mutex is in the env, use it */ + val = getenv(MUTEX_VARNAME); + if (val != NULL) + { + acceptMutex = (HANDLE) atoi(val); + } } - /* * Determine if this library is being used to listen for FastCGI * connections. This is communicated by STDIN containing a @@ -420,7 +432,6 @@ if (SetNamedPipeHandleState(hListen, &pipeMode, NULL, NULL)) { listenType = FD_PIPE_SYNC; - listenOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); } else { @@ -458,7 +469,6 @@ DebugBreak(); exit(99); */ - return -1; } if ((fakeFd = Win32NewDescriptor(FD_PIPE_SYNC, @@ -494,10 +504,8 @@ */ if((cLenPtr = getenv("CONTENT_LENGTH")) != NULL && atoi(cLenPtr) > 0) { - hStdinThread = CreateThread(NULL, 8192, - (LPTHREAD_START_ROUTINE)&StdinThread, - NULL, 0, &threadId); - if (hStdinThread == NULL) { + hStdinThread = (HANDLE) _beginthread(StdinThread, 0, NULL); + if (hStdinThread == (HANDLE) -1) { printf("<H2>OS_LibInit Failed to create STDIN thread! ERROR: %d</H2>\r\n\r\n", GetLastError()); return -1; @@ -582,7 +590,6 @@ if (acceptMutex != INVALID_HANDLE_VALUE) { ReleaseMutex(acceptMutex); - CloseHandle(acceptMutex); } /* we only want to do this if we're not a web server */ @@ -592,7 +599,6 @@ if (bImpersonate) RevertToSelf(); } - DeleteCriticalSection(&fdTableCritical); WSACleanup(); } @@ -624,15 +630,13 @@ { case FD_FILE_SYNC: case FD_FILE_ASYNC: - + /* Free file path string */ ASSERT(fdTable[fd].path != NULL); - free(fdTable[fd].path); fdTable[fd].path = NULL; break; - case FD_PIPE_ASYNC: - break; + default: break; } @@ -769,25 +773,17 @@ * *---------------------------------------------------------------------- */ -int OS_CreateLocalIpcFd(const char *bindPath, int backlog, int bCreateMutex) +int OS_CreateLocalIpcFd(const char *bindPath, int backlog) { int pseudoFd = -1; short port = getPort(bindPath); - HANDLE mutex = INVALID_HANDLE_VALUE; - char mutexEnvString[100]; - if (bCreateMutex) { - mutex = CreateMutex(NULL, FALSE, NULL); - if (! SetHandleInformation(mutex, HANDLE_FLAG_INHERIT, TRUE)) - { - CloseHandle(mutex); - return -3; - } - // This is a nail for listening to more than one port.. - // This should really be handled by the caller. - _snprintf(mutexEnvString, sizeof(mutexEnvString)-1, MUTEX_VARNAME "=%d", (int) mutex); - putenv(mutexEnvString); - } + if (acceptMutex == INVALID_HANDLE_VALUE) + { + acceptMutex = CreateMutex(NULL, FALSE, NULL); + if (acceptMutex == NULL) return -2; + if (! SetHandleInformation(acceptMutex, HANDLE_FLAG_INHERIT, TRUE)) return -3; + } // There's nothing to be gained (at the moment) by a shutdown Event @@ -798,7 +794,6 @@ "You should either use \"localhost:<port>\" or " " just use \":<port>.\"\n"); //exit(1); - if (bCreateMutex) CloseHandle(mutexEnvString); return -1; } @@ -818,19 +813,16 @@ listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock == INVALID_SOCKET) { - if (bCreateMutex)CloseHandle(mutexEnvString); return -4; } if (bind(listenSock, (struct sockaddr *) &sockAddr, sockLen) ) { - if (bCreateMutex)CloseHandle(mutexEnvString); return -12; } if (listen(listenSock, backlog)) { - if (bCreateMutex)CloseHandle(mutexEnvString); return -5; } @@ -838,7 +830,6 @@ if (pseudoFd == -1) { - if (bCreateMutex)CloseHandle(mutexEnvString); closesocket(listenSock); return -6; } @@ -858,7 +849,6 @@ if (! pipePath) { - if (bCreateMutex)CloseHandle(mutexEnvString); return -7; } @@ -897,7 +887,7 @@ } hListenPipe = CreateNamedPipe(pipePath, - PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, + PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, bImpersonate?&sa:NULL); @@ -906,13 +896,11 @@ if (hListenPipe == INVALID_HANDLE_VALUE) { - if (bCreateMutex)CloseHandle(mutexEnvString); return -8; } if (! SetHandleInformation(hListenPipe, HANDLE_FLAG_INHERIT, TRUE)) { - if (bCreateMutex)CloseHandle(mutexEnvString); return -9; } @@ -920,7 +908,6 @@ if (pseudoFd == -1) { - if (bCreateMutex)CloseHandle(mutexEnvString); CloseHandle(hListenPipe); return -10; } @@ -1107,7 +1094,6 @@ else { fdTable[fd].Errno = GetLastError(); - ret = -1; } break; @@ -1226,14 +1212,13 @@ StartupInfo.lpReserved2 = NULL; StartupInfo.cbReserved2 = 0; StartupInfo.lpDesktop = NULL; - StartupInfo.wShowWindow = SW_HIDE; /* * FastCGI on NT will set the listener pipe HANDLE in the stdin of * the new process. The fact that there is a stdin and NULL handles * for stdout and stderr tells the FastCGI process that this is a * FastCGI process and not a CGI process. */ - StartupInfo.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; + StartupInfo.dwFlags = STARTF_USESTDHANDLES; /* * XXX: Do I have to dup the handle before spawning the process or is * it sufficient to use the handle as it's reference counted @@ -1508,7 +1493,7 @@ * *-------------------------------------------------------------- */ -int OS_Close(int fd) +int OS_Close(int fd, int shutdown_ok) { int ret = 0; @@ -1523,45 +1508,53 @@ case FD_PIPE_ASYNC: case FD_FILE_SYNC: case FD_FILE_ASYNC: - /* - * CloseHandle returns: TRUE success, 0 failure - */ - /* - XXX don't close here, fcgi apps fail if we do so - need to examine resource leaks if any might exist - if (CloseHandle(fdTable[fd].fid.fileHandle) == FALSE) - ret = -1; - */ + break; + case FD_SOCKET_SYNC: - case FD_SOCKET_ASYNC: - /* - * Closing a socket that has an async read outstanding causes a - * tcp reset and possible data loss. The shutdown call seems to - * prevent this. - */ + case FD_SOCKET_ASYNC: - /* shutdown(fdTable[fd].fid.sock, SD_BOTH); */ + /* + * 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) { - char buf[16]; - int r; + if (shutdown(fdTable[fd].fid.sock, SD_SEND) == 0) + { + struct timeval tv; + fd_set rfds; + int sock = fdTable[fd].fid.sock; + int rv; + char trash[1024]; - shutdown(fdTable[fd].fid.sock,SD_SEND); + FD_ZERO(&rfds); - do - { - r = recv(fdTable[fd].fid.sock,buf,16,0); - } while (r > 0); + do + { +#pragma warning( disable : 4127 ) + FD_SET((unsigned) sock, &rfds); +#pragma warning( default : 4127 ) + + tv.tv_sec = 2; + tv.tv_usec = 0; + rv = select(sock + 1, &rfds, NULL, NULL, &tv); + } + while (rv > 0 && recv(sock, trash, sizeof(trash), 0) > 0); + } } - /* - * closesocket returns: 0 success, SOCKET_ERROR failure - */ - if (closesocket(fdTable[fd].fid.sock) == SOCKET_ERROR) - ret = -1; - break; - default: - return -1; /* fake failure */ + + closesocket(fdTable[fd].fid.sock); + + break; + + default: + + ret = -1; /* fake failure */ } Win32FreeDescriptor(fd); @@ -1711,7 +1704,7 @@ } #endif -static printLastError(const char * text) +static void printLastError(const char * text) { LPVOID buf; @@ -1735,7 +1728,7 @@ { int ipcFd = -1; - if (! ConnectNamedPipe(hListen, &listenOverlapped)) + if (! ConnectNamedPipe(hListen, NULL)) { switch (GetLastError()) { @@ -1748,19 +1741,9 @@ case ERROR_IO_PENDING: - // Wait for a connection to complete. - - while (WaitForSingleObject(listenOverlapped.hEvent, - ACCEPT_TIMEOUT) == WAIT_TIMEOUT) - { - if (shutdownPending) - { - OS_LibShutdown(); - return -1; - } - } - - break; + // The NamedPipe was opened with an Overlapped structure + // and there is a pending io operation. mod_fastcgi + // did this in 2.2.12 (fcgi_pm.c v1.52). case ERROR_PIPE_LISTENING: @@ -1810,7 +1793,10 @@ fd_set readfds; FD_ZERO(&readfds); + +#pragma warning( disable : 4127 ) FD_SET((unsigned int) hListen, &readfds); +#pragma warning( default : 4127 ) if (select(0, &readfds, NULL, NULL, &timeout) == 0) { @@ -1914,11 +1900,15 @@ if (acceptMutex != INVALID_HANDLE_VALUE) { DWORD ret; +#if YOU_WANT_TO_MAKE_THE_PROCESS_HANG_AFTER_FIRST_REQUEST while ((ret = WaitForSingleObject(acceptMutex, ACCEPT_TIMEOUT)) == WAIT_TIMEOUT) { if (shutdownPending) break; } if (ret == WAIT_FAILED) { +#else + if (WaitForSingleObject(acceptMutex, INFINITE) == WAIT_FAILED) { +#endif printLastError("WaitForSingleObject() failed"); return -1; } @@ -1964,10 +1954,9 @@ * *---------------------------------------------------------------------- */ -int OS_IpcClose(int ipcFd) +int OS_IpcClose(int ipcFd, int shutdown) { - if (ipcFd == -1) - return 0; + if (ipcFd == -1) return 0; /* * Catch it if fd is a bogus value @@ -1975,36 +1964,32 @@ ASSERT((ipcFd >= 0) && (ipcFd < WIN32_OPEN_MAX)); ASSERT(fdTable[ipcFd].type != FD_UNUSED); - switch(listenType) { - + switch (listenType) + { case FD_PIPE_SYNC: - /* - * Make sure that the client (ie. a Web Server in this case) has - * read all data from the pipe before we disconnect. - */ - if(!FlushFileBuffers(fdTable[ipcFd].fid.fileHandle)) - return -1; - if(DisconnectNamedPipe(fdTable[ipcFd].fid.fileHandle)) { - OS_Close(ipcFd); - if (bImpersonate) RevertToSelf(); - return 0; - } else { - return -1; - } - break; + /* + * Make sure that the client (ie. a Web Server in this case) has + * read all data from the pipe before we disconnect. + */ + if (! FlushFileBuffers(fdTable[ipcFd].fid.fileHandle)) return -1; + if (! DisconnectNamedPipe(fdTable[ipcFd].fid.fileHandle)) return -1; + + if (bImpersonate) RevertToSelf(); + + /* fall through */ case FD_SOCKET_SYNC: - OS_Close(ipcFd); - return 0; - break; + + OS_Close(ipcFd, shutdown); + break; case FD_UNUSED: default: - //exit(106); - return -1; - break; + return -1; + break; } - return -1; + + return 0; } /* Index: php-src/sapi/cgi/libfcgi/include/fastcgi.h diff -u php-src/sapi/cgi/libfcgi/include/fastcgi.h:1.1 php-src/sapi/cgi/libfcgi/include/fastcgi.h:1.1.4.1 --- php-src/sapi/cgi/libfcgi/include/fastcgi.h:1.1 Sun Mar 10 16:39:28 2002 +++ php-src/sapi/cgi/libfcgi/include/fastcgi.h Sun Sep 21 18:08:17 2003 @@ -9,7 +9,7 @@ * See the file "LICENSE.TERMS" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * $Id: fastcgi.h,v 1.1 2002/03/10 21:39:28 shane Exp $ + * $Id: fastcgi.h,v 1.1.4.1 2003/09/21 22:08:17 sas Exp $ */ #ifndef _FASTCGI_H Index: php-src/sapi/cgi/libfcgi/include/fcgi_config_win32.h diff -u php-src/sapi/cgi/libfcgi/include/fcgi_config_win32.h:1.1.2.1 php-src/sapi/cgi/libfcgi/include/fcgi_config_win32.h:1.1.2.2 --- php-src/sapi/cgi/libfcgi/include/fcgi_config_win32.h:1.1.2.1 Sun Dec 1 18:15:31 2002 +++ php-src/sapi/cgi/libfcgi/include/fcgi_config_win32.h Sun Sep 21 18:08:17 2003 @@ -1,111 +1,39 @@ -/* fcgi_config.h. Generated automatically by configure. */ -/* fcgi_config.h.in. Generated automatically from configure.in by autoheader. */ +/* + * Copied to fcgi_config.h when building on WinNT without cygwin, + * i.e. configure is not run. See fcgi_config.h.in for details. + */ -/* Define if you have the <arpa/inet.h> header file. */ -#define HAVE_ARPA_INET_H 1 - -/* Define if you have the <dlfcn.h> header file. */ -#define HAVE_DLFCN_H 1 - -/* Define if there's a fileno() prototype in stdio.h */ -#define HAVE_FILENO_PROTO 1 - -/* Define if the fpos_t typedef is in stdio.h */ #define HAVE_FPOS 1 - -/* Define if you have the <inttypes.h> header file. */ -#define HAVE_INTTYPES_H 1 - -/* Define if you have the `dnet_stub' library (-ldnet_stub). */ -/* #undef HAVE_LIBDNET_STUB */ - -/* Define if you have the `ieee' library (-lieee). */ -/* #undef HAVE_LIBIEEE */ - -/* Define if you have the `nsl' library (-lnsl). */ -#define HAVE_LIBNSL 1 - -/* Define if you have the pthread library */ -#define HAVE_LIBPTHREAD 1 - -/* Define if you have the `resolv' library (-lresolv). */ -#define HAVE_LIBRESOLV 1 - -/* Define if you have the `socket' library (-lsocket). */ -#define HAVE_LIBSOCKET 1 - -/* Define if you have the <limits.h> header file. */ #define HAVE_LIMITS_H 1 - -/* Define if you have the <memory.h> header file. */ -#define HAVE_MEMORY_H 1 - -/* Define if you have the <netdb.h> header file. */ -/* #define HAVE_NETDB_H 1 */ - -/* Define if you have the <netinet/in.h> header file. */ -#define HAVE_NETINET_IN_H 1 - -/* Define if sockaddr_un in sys/un.h contains a sun_len component */ -/* #undef HAVE_SOCKADDR_UN_SUN_LEN */ - -/* Define if the socklen_t typedef is in sys/socket.h */ -/* #undef HAVE_SOCKLEN */ - -/* Define if you have the <stdint.h> header file. */ -/* #undef HAVE_STDINT_H */ - -/* Define if you have the <stdlib.h> header file. */ -#define HAVE_STDLIB_H 1 - -/* Define if you have the `strerror' function. */ +#define HAVE_STREAMBUF_CHAR_TYPE 1 #define HAVE_STRERROR 1 - -/* Define if you have the <strings.h> header file. */ -#define HAVE_STRINGS_H 1 - -/* Define if you have the <string.h> header file. */ -#define HAVE_STRING_H 1 - -/* Define if you have the <sys/param.h> header file. */ -/* #define HAVE_SYS_PARAM_H 1 */ - -/* Define if you have the <sys/socket.h> header file. */ -/*#define HAVE_SYS_SOCKET_H 1*/ - -/* Define if you have the <sys/stat.h> header file. */ -#define HAVE_SYS_STAT_H 1 - -/* Define if you have the <sys/time.h> header file. */ -/*#define HAVE_SYS_TIME_H 1*/ - -/* Define if you have the <sys/types.h> header file. */ -#define HAVE_SYS_TYPES_H 1 - -/* Define if you have the <unistd.h> header file. */ -/*#define HAVE_UNISTD_H 1*/ - -/* Define if va_arg(arg, long double) crashes the compiler */ -/* #undef HAVE_VA_ARG_LONG_DOUBLE_BUG */ - -/* Name of package */ -#define PACKAGE "fcgi" - -/* Define if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Define if cross-process locking is required by accept() */ -#define USE_LOCKING 1 - -/* Version number of package */ -#define VERSION "2.2.2" - -/* Define to empty if `const' does not conform to ANSI C. */ -/* #undef const */ - -/* Define as `__inline' if that's what the C compiler calls it, or to nothing - if it is not supported. */ -/* #undef inline */ - -/* Define to `int' if <sys/types.h> does not define. */ -#define ssize_t int \ No newline at end of file +#undef HAVE_ARPA_INET_H +#undef HAVE_DLFCN_H +#undef HAVE_FILENO_PROTO +#undef HAVE_INTTYPES_H +#undef HAVE_IOSTREAM_WITHASSIGN_STREAMBUF +#undef HAVE_LIBNSL +#undef HAVE_LIBSOCKET +#undef HAVE_MEMORY_H +#undef HAVE_NETDB_H +#undef HAVE_NETINET_IN_H +#undef HAVE_PTHREAD +#undef HAVE_SOCKADDR_UN_SUN_LEN +#undef HAVE_SOCKLEN +#undef HAVE_STDINT_H +#undef HAVE_STDLIB_H +#undef HAVE_STRING_H +#undef HAVE_STRINGS_H +#undef HAVE_SYS_PARAM_H +#undef HAVE_SYS_SOCKET_H +#undef HAVE_SYS_STAT_H +#undef HAVE_SYS_TIME_H +#undef HAVE_SYS_TYPES_H +#undef HAVE_UNISTD_H +#undef HAVE_VA_ARG_LONG_DOUBLE_BUG +#undef PTHREAD_CREATE_JOINABLE +#undef STDC_HEADERS +#undef USE_LOCKING +#undef const +#undef inline +#undef ssize_t Index: php-src/sapi/cgi/libfcgi/include/fcgi_stdio.h diff -u php-src/sapi/cgi/libfcgi/include/fcgi_stdio.h:1.1 php-src/sapi/cgi/libfcgi/include/fcgi_stdio.h:1.1.4.1 --- php-src/sapi/cgi/libfcgi/include/fcgi_stdio.h:1.1 Sun Mar 10 16:39:28 2002 +++ php-src/sapi/cgi/libfcgi/include/fcgi_stdio.h Sun Sep 21 18:08:17 2003 @@ -9,7 +9,7 @@ * See the file "LICENSE.TERMS" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * $Id: fcgi_stdio.h,v 1.1 2002/03/10 21:39:28 shane Exp $ + * $Id: fcgi_stdio.h,v 1.1.4.1 2003/09/21 22:08:17 sas Exp $ */ #ifndef _FCGI_STDIO @@ -25,11 +25,7 @@ #ifndef DLLAPI #ifdef _WIN32 -#if defined(_LIB) || defined(FCGI_STATIC) -#define DLLAPI -#else #define DLLAPI __declspec(dllimport) -#endif #else #define DLLAPI #endif Index: php-src/sapi/cgi/libfcgi/include/fcgiapp.h diff -u php-src/sapi/cgi/libfcgi/include/fcgiapp.h:1.1.4.1 php-src/sapi/cgi/libfcgi/include/fcgiapp.h:1.1.4.2 --- php-src/sapi/cgi/libfcgi/include/fcgiapp.h:1.1.4.1 Sun Dec 1 18:11:15 2002 +++ php-src/sapi/cgi/libfcgi/include/fcgiapp.h Sun Sep 21 18:08:17 2003 @@ -9,7 +9,7 @@ * See the file "LICENSE.TERMS" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * $Id: fcgiapp.h,v 1.1.4.1 2002/12/01 23:11:15 shane Exp $ + * $Id: fcgiapp.h,v 1.1.4.2 2003/09/21 22:08:17 sas Exp $ */ #ifndef _FCGIAPP_H @@ -24,11 +24,7 @@ #ifndef DLLAPI #ifdef _WIN32 -#if defined(_LIB) || defined(FCGI_STATIC) -#define DLLAPI -#else #define DLLAPI __declspec(dllimport) -#endif #else #define DLLAPI #endif @@ -80,19 +76,6 @@ typedef char **FCGX_ParamArray; /* - * A vector of pointers representing the parameters received - * by a FastCGI application server, with the vector's length - * and last valid element so adding new parameters is efficient. - */ - -typedef struct Params { - FCGX_ParamArray vec; /* vector of strings */ - int length; /* number of string vec can hold */ - char **cur; /* current item in vec; *cur == NULL */ -} Params; -typedef Params *ParamsPtr; - -/* * FCGX_Request Flags * * Setting FCGI_FAIL_ACCEPT_ON_INTR prevents FCGX_Accept() from @@ -111,18 +94,19 @@ FCGX_Stream *in; FCGX_Stream *out; FCGX_Stream *err; - FCGX_ParamArray envp; + char **envp; - /* Don't use anything below here */ + /* Don't use anything below here */ - ParamsPtr paramsPtr; + struct Params *paramsPtr; int ipcFd; /* < 0 means no connection */ int isBeginProcessed; /* FCGI_BEGIN_REQUEST seen */ int keepConnection; /* don't close ipcFd at end of request */ int appStatus; int nWriters; /* number of open writers (0..2) */ - int flags; - int listen_sock; + int flags; + int listen_sock; + int detached; } FCGX_Request; @@ -632,6 +616,15 @@ * ---------------------------------------------------------------------- */ DLLAPI void FCGX_ShutdownPending(void); + + +/* + * Attach/Detach an accepted request from its listen socket. + * XXX This is not fully implemented at this time (patch welcome). + */ +DLLAPI int FCGX_Attach(FCGX_Request * r); +DLLAPI int FCGX_Detach(FCGX_Request * r); + #if defined (__cplusplus) || defined (c_plusplus) } /* terminate extern "C" { */ Index: php-src/sapi/cgi/libfcgi/include/fcgimisc.h diff -u php-src/sapi/cgi/libfcgi/include/fcgimisc.h:1.1 php-src/sapi/cgi/libfcgi/include/fcgimisc.h:1.1.4.1 --- php-src/sapi/cgi/libfcgi/include/fcgimisc.h:1.1 Sun Mar 10 16:39:28 2002 +++ php-src/sapi/cgi/libfcgi/include/fcgimisc.h Sun Sep 21 18:08:17 2003 @@ -9,7 +9,7 @@ * See the file "LICENSE.TERMS" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * $Id: fcgimisc.h,v 1.1 2002/03/10 21:39:28 shane Exp $ + * $Id: fcgimisc.h,v 1.1.4.1 2003/09/21 22:08:17 sas Exp $ */ #ifndef _FCGIMISC_H Index: php-src/sapi/cgi/libfcgi/include/fcgio.h diff -u php-src/sapi/cgi/libfcgi/include/fcgio.h:1.1 php-src/sapi/cgi/libfcgi/include/fcgio.h:1.1.4.1 --- php-src/sapi/cgi/libfcgi/include/fcgio.h:1.1 Sun Mar 10 16:39:28 2002 +++ php-src/sapi/cgi/libfcgi/include/fcgio.h Sun Sep 21 18:08:17 2003 @@ -1,7 +1,7 @@ // // Provides support for FastCGI via C++ iostreams. // -// $Id: fcgio.h,v 1.1 2002/03/10 21:39:28 shane Exp $ +// $Id: fcgio.h,v 1.1.4.1 2003/09/21 22:08:17 sas Exp $ // // This work is based on routines written by George Feinberg. They // have been mostly re-written and extensively changed by @@ -30,7 +30,7 @@ #ifndef FCGIO_H #define FCGIO_H -#include <iostream.h> +#include <iostream> #include "fcgiapp.h" @@ -42,10 +42,14 @@ #endif #endif +#if ! HAVE_STREAMBUF_CHAR_TYPE +typedef char char_type; +#endif + /* * fcgi_streambuf */ -class fcgi_streambuf : public streambuf +class DLLAPI fcgi_streambuf : public std::streambuf { public: @@ -54,50 +58,50 @@ // assigned, I/O is a bit less effecient and output streams will // have to be flushed (or the streambuf destroyed) before the next // call to "accept". - DLLAPI fcgi_streambuf(FCGX_Stream * fcgx, char * buf, int len); + fcgi_streambuf(FCGX_Stream * fcgx, char * buf, int len); - DLLAPI fcgi_streambuf(char * buf, int len); + fcgi_streambuf(char_type * buf, std::streamsize len); - DLLAPI fcgi_streambuf(FCGX_Stream * fcgx = NULL); + fcgi_streambuf(FCGX_Stream * fcgx = 0); - DLLAPI ~fcgi_streambuf(void); + ~fcgi_streambuf(void); - DLLAPI int attach(FCGX_Stream * fcgx); + int attach(FCGX_Stream * fcgx); protected: // Consume the put area (if buffered) and c (if c is not EOF). - DLLAPI virtual int overflow(int); + virtual int overflow(int); // Flush the put area (if buffered) and the FCGX buffer to the client. - DLLAPI virtual int sync(); + virtual int sync(); // Remove and return the current character. - DLLAPI virtual int uflow(); + virtual int uflow(); // Fill the get area (if buffered) and return the current character. - DLLAPI virtual int underflow(); + virtual int underflow(); // Use a buffer. The only reasons that a buffer would be useful is // to support the use of the unget()/putback() or seek() methods. Using // a buffer will result in less efficient I/O. Note: the underlying // FastCGI library (FCGX) maintains its own input and output buffers. - DLLAPI virtual streambuf * setbuf(char * buf, int len); + virtual std::streambuf * setbuf(char_type * buf, std::streamsize len); - DLLAPI virtual int xsgetn(char * s, int n); - DLLAPI virtual int xsputn(const char * s, int n); + virtual std::streamsize xsgetn(char_type * s, std::streamsize n); + virtual std::streamsize xsputn(const char_type * s, std::streamsize n); private: FCGX_Stream * fcgx; // buf is just handy to have around - char * buf; + char_type * buf; // this isn't kept by the base class - int bufsize; + std::streamsize bufsize; - void init(FCGX_Stream * fcgx, char * buf, int bufsize); + void init(FCGX_Stream * fcgx, char_type * buf, std::streamsize bufsize); void reset(void); }; @@ -105,18 +109,18 @@ /* * fcgi_istream - deprecated */ -class fcgi_istream : public istream +class DLLAPI fcgi_istream : public std::istream { public: // deprecated - DLLAPI fcgi_istream(FCGX_Stream * fcgx = NULL); + fcgi_istream(FCGX_Stream * fcgx = 0); // deprecated - DLLAPI ~fcgi_istream(void) {} + ~fcgi_istream(void) {} // deprecated - DLLAPI virtual void attach(FCGX_Stream * fcgx); + virtual void attach(FCGX_Stream * fcgx); private: @@ -126,18 +130,18 @@ /* * fcgi_ostream - deprecated */ -class fcgi_ostream : public ostream +class DLLAPI fcgi_ostream : public std::ostream { public: // deprecated - DLLAPI fcgi_ostream(FCGX_Stream * fcgx = NULL); + fcgi_ostream(FCGX_Stream * fcgx = 0); // deprecated - DLLAPI ~fcgi_ostream(void) {} + ~fcgi_ostream(void) {} // deprecated - DLLAPI virtual void attach(FCGX_Stream *fcgx); + virtual void attach(FCGX_Stream *fcgx); private: Index: php-src/sapi/cgi/libfcgi/include/fcgios.h diff -u php-src/sapi/cgi/libfcgi/include/fcgios.h:1.2.4.1 php-src/sapi/cgi/libfcgi/include/fcgios.h:1.2.4.2 --- php-src/sapi/cgi/libfcgi/include/fcgios.h:1.2.4.1 Sun Dec 1 18:11:15 2002 +++ php-src/sapi/cgi/libfcgi/include/fcgios.h Sun Sep 21 18:08:17 2003 @@ -30,6 +30,10 @@ #include <sys/time.h> #endif +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif + #if defined (c_plusplus) || defined (__cplusplus) extern "C" { #endif @@ -47,11 +51,7 @@ #ifndef DLLAPI #ifdef _WIN32 -#if defined(_LIB) || defined(FCGI_STATIC) -#define DLLAPI -#else #define DLLAPI __declspec(dllimport) -#endif #else #define DLLAPI #endif @@ -97,33 +97,31 @@ # endif /* __STDC__ */ #define _CLIENTDATA #endif -#define MUTEX_VARNAME "_FCGI_MUTEX_" -#define SHUTDOWN_EVENT_NAME "_FCGI_SHUTDOWN_EVENT_" typedef void (*OS_AsyncProc) (ClientData clientData, int len); DLLAPI int OS_LibInit(int stdioFds[3]); DLLAPI void OS_LibShutdown(void); -DLLAPI int OS_CreateLocalIpcFd(const char *bindPath, int backlog, int bCreateMutex); +DLLAPI int OS_CreateLocalIpcFd(const char *bindPath, int backlog); DLLAPI int OS_FcgiConnect(char *bindPath); DLLAPI int OS_Read(int fd, char * buf, size_t len); DLLAPI int OS_Write(int fd, char * buf, size_t len); #ifdef _WIN32 -DLLAPI int OS_SpawnChild(char *execPath, int listenFd, PROCESS_INFORMATION *pInfo, char *env); +DLLAPI int OS_SpawnChild(char *execPath, int listenFd, PROCESS_INFORMATION *, char *); #else -DLLAPI int OS_SpawnChild(char *execPath, int listenfd); +DLLAPI int OS_SpawnChild(char *execPath, int listenFd); #endif DLLAPI int OS_AsyncReadStdin(void *buf, int len, OS_AsyncProc procPtr, - ClientData clientData); + ClientData clientData); DLLAPI int OS_AsyncRead(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData); + OS_AsyncProc procPtr, ClientData clientData); DLLAPI int OS_AsyncWrite(int fd, int offset, void *buf, int len, - OS_AsyncProc procPtr, ClientData clientData); -DLLAPI int OS_Close(int fd); + OS_AsyncProc procPtr, ClientData clientData); +DLLAPI int OS_Close(int fd, int shutdown); DLLAPI int OS_CloseRead(int fd); DLLAPI int OS_DoIo(struct timeval *tmo); DLLAPI int OS_Accept(int listen_sock, int fail_on_intr, const char *webServerAddrs); -DLLAPI int OS_IpcClose(int ipcFd); +DLLAPI int OS_IpcClose(int ipcFd, int shutdown); DLLAPI int OS_IsFcgi(int sock); DLLAPI void OS_SetFlags(int fd, int flags);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php