diff options
author | George Wang <gwang@php.net> | 2018-02-27 13:54:28 -0500 |
---|---|---|
committer | George Wang <gwang@php.net> | 2018-02-27 13:54:28 -0500 |
commit | 97ff815cbbfe524a46ab5e76312d19a4b3771079 (patch) | |
tree | 86247f316a8dcc8783f6e38216f906090a02a23d /sapi/litespeed/lsapilib.c | |
parent | ea4ba9d008d4b3953dcd74a69d2f2b6aa620fd81 (diff) | |
download | php-git-97ff815cbbfe524a46ab5e76312d19a4b3771079.tar.gz |
release LiteSpeed SAPI 7.0.
add CRIU support.
add support for [PATH=] and [HOST=] sections in php.ini
Diffstat (limited to 'sapi/litespeed/lsapilib.c')
-rw-r--r-- | sapi/litespeed/lsapilib.c | 724 |
1 files changed, 556 insertions, 168 deletions
diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c index 9f58901432..185435a42d 100644 --- a/sapi/litespeed/lsapilib.c +++ b/sapi/litespeed/lsapilib.c @@ -17,7 +17,7 @@ */ /* -Copyright (c) 2002-2015, Lite Speed Technologies Inc. +Copyright (c) 2002-2018, Lite Speed Technologies Inc. All rights reserved. Redistribution and use in source and binary forms, with or without @@ -53,11 +53,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <dlfcn.h> #include <errno.h> #include <fcntl.h> - +#include <limits.h> #include <sys/stat.h> #include <signal.h> #include <stdlib.h> #include <stdio.h> +#include <stdarg.h> #include <string.h> #include <sys/mman.h> #include <sys/resource.h> @@ -116,22 +117,50 @@ typedef struct lsapi_MD5Context lsapi_MD5_CTX; #define LSAPI_RESP_BUF_SIZE 8192 #define LSAPI_INIT_RESP_HEADER_LEN 4096 +typedef struct _lsapi_child_status +{ + int m_pid; + long m_tmStart; + + volatile short m_iKillSent; + volatile char m_inProcess; + volatile char m_connected; + volatile int m_iReqCounter; + + volatile long m_tmWaitBegin; + volatile long m_tmReqBegin; + volatile long m_tmLastCheckPoint; +} +lsapi_child_status; +static lsapi_child_status * s_worker_status = NULL; static int g_inited = 0; static int g_running = 1; static int s_ppid; +static int s_restored_ppid = 0; +static int s_pid = 0; static int s_slow_req_msecs = 0; static int s_keepListener = 0; static int s_dump_debug_info = 0; static int s_pid_dump_debug_info = 0; +static int s_req_processed = 0; + +static int *s_busy_workers = NULL; +static int *s_accepting_workers = NULL; +static int *s_global_counter = &s_req_processed; +static int s_max_busy_workers = -1; +static char *s_stderr_log_path = NULL; -LSAPI_Request g_req = { -1, -1 }; +LSAPI_Request g_req = +{ .m_fdListen = -1, .m_fd = -1 }; static char s_secret[24]; +static LSAPI_On_Timer_pf s_proc_group_timer_cb = NULL; void Flush_RespBuf_r( LSAPI_Request * pReq ); +static int lsapi_reopen_stderr(const char *p); static const char *CGI_HEADERS[H_TRANSFER_ENCODING+1] = { @@ -185,9 +214,92 @@ static int HTTP_HEADER_LEN[H_TRANSFER_ENCODING+1] = 13,17, 8, 13, 8, 19, 10, 5, 15, 3, 17 }; + +static const char *s_log_level_names[8] = +{ + "", "DEBUG","INFO", "NOTICE", "WARN", "ERROR", "CRIT", "FATAL" +}; + + +void LSAPI_Log(int flag, const char * fmt, ...) +{ + char buf[1024]; + char *p = buf; + if (flag & LSAPI_LOG_TIMESTAMP_BITS) + { + struct timeval tv; + struct tm tm; + gettimeofday(&tv, NULL); + localtime_r(&tv.tv_sec, &tm); + if (flag & LSAPI_LOG_TIMESTAMP_FULL) + { + p += snprintf(p, 1024, "%04d-%02d-%02d %02d:%02d:%02d.%06d ", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, + tm.tm_hour, tm.tm_min, tm.tm_sec, (int)tv.tv_usec); + } + else if (flag & LSAPI_LOG_TIMESTAMP_HMS) + { + p += snprintf(p, 1024, "%02d:%02d:%02d ", + tm.tm_hour, tm.tm_min, tm.tm_sec); + } + } + + int level = flag & LSAPI_LOG_LEVEL_BITS; + if (level && level <= LSAPI_LOG_FLAG_FATAL) + { + p += snprintf(p, 100, "[%s] ", s_log_level_names[level]); + } + + if (flag & LSAPI_LOG_PID) + { + p += snprintf(p, 100, "[%d] ", s_pid); + } + + if (p > buf) + fprintf(stderr, "%.*s", (int)(p - buf), buf); + va_list ap; + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +#ifdef LSAPI_DEBUG + +#define DBGLOG_FLAG (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_DEBUG|LSAPI_LOG_PID) +#define lsapi_dbg(...) LSAPI_Log(DBGLOG_FLAG, __VA_ARGS__) + +#else + +#define lsapi_dbg(...) + +#endif + + +static int lsapi_parent_dead() +{ + // Return non-zero if the parent is dead. 0 if still alive. + if (!s_ppid) { + // not checking, so not dead + return(0); + } + if (s_restored_ppid) { + if (kill(s_restored_ppid,0) == -1) { + if (errno == EPERM) { + return(0); // no permission, but it's still there. + } + return(1); // Dead + } + return(0); // it worked, so it's not dead + } + return(s_ppid != getppid()); +} + + static void lsapi_sigpipe( int sig ) { } + + static void lsapi_siguser1( int sig ) { g_running = 0; @@ -214,7 +326,7 @@ static void lsapi_signal(int signo, sighandler_t handler) static int s_enable_core_dump = 0; -static void lsapi_enable_core_dump() +static void lsapi_enable_core_dump(void) { #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) \ || defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) @@ -251,6 +363,7 @@ static inline void lsapi_buildPacketHeader( struct lsapi_packet_header * pHeader pHeader->m_packetLen.m_iLen = len; } + static int lsapi_set_nblock( int fd, int nonblock ) { int val = fcntl( fd, F_GETFL, 0 ); @@ -271,6 +384,7 @@ static int lsapi_set_nblock( int fd, int nonblock ) return 0; } + static int lsapi_close( int fd ) { int ret; @@ -283,6 +397,20 @@ static int lsapi_close( int fd ) } } + +static void lsapi_close_connection(LSAPI_Request *pReq) +{ + if (pReq->m_fd == -1) + return; + lsapi_close(pReq->m_fd); + pReq->m_fd = -1; + if (s_busy_workers) + __sync_fetch_and_sub(s_busy_workers, 1); + if (s_worker_status) + s_worker_status->m_connected = 0; +} + + static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len ) { ssize_t ret; @@ -295,6 +423,7 @@ static inline ssize_t lsapi_read( int fd, void * pBuf, size_t len ) } } + /* static int lsapi_write( int fd, const void * pBuf, int len ) { @@ -317,6 +446,7 @@ static int lsapi_write( int fd, const void * pBuf, int len ) } */ + static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen ) { int ret; @@ -361,6 +491,7 @@ static int lsapi_writev( int fd, struct iovec ** pVec, int count, int totalLen ) return totalLen - left; } + /* static int getTotalLen( struct iovec * pVec, int count ) { @@ -375,6 +506,7 @@ static int getTotalLen( struct iovec * pVec, int count ) } */ + static inline int allocateBuf( LSAPI_Request * pReq, int size ) { char * pBuf = (char *)realloc( pReq->m_pReqBuf, size ); @@ -402,6 +534,7 @@ static int allocateIovec( LSAPI_Request * pReq, int n ) return 0; } + static int allocateRespHeaderBuf( LSAPI_Request * pReq, int size ) { char * p = (char *)realloc( pReq->m_pRespHeaderBuf, size ); @@ -433,6 +566,7 @@ static inline int verifyHeader( struct lsapi_packet_header * pHeader, char pktTy return pHeader->m_packetLen.m_iLen; } + static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList, int *curSize, int newSize ) { @@ -454,6 +588,7 @@ static int allocateEnvList( struct LSAPI_key_value_pair ** pEnvList, } + static inline int isPipe( int fd ) { char achPeer[128]; @@ -465,6 +600,7 @@ static inline int isPipe( int fd ) return 1; } + static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, char **pBegin, char * pEnd ) { @@ -501,6 +637,7 @@ static int parseEnv( struct LSAPI_key_value_pair * pEnvList, int count, return 0; } + static inline void swapIntEndian( int * pInteger ) { char * p = (char *)pInteger; @@ -514,6 +651,7 @@ static inline void swapIntEndian( int * pInteger ) } + static inline void fixEndian( LSAPI_Request * pReq ) { struct lsapi_req_header *p= pReq->m_pHeader; @@ -528,6 +666,7 @@ static inline void fixEndian( LSAPI_Request * pReq ) swapIntEndian( &p->m_cntSpecialEnv ); } + static void fixHeaderIndexEndian( LSAPI_Request * pReq ) { int i; @@ -614,7 +753,7 @@ static int (*fp_lve_destroy)(struct liblve *) = NULL; static int (*fp_lve_enter)(struct liblve *, uint32_t, int32_t, int32_t, uint32_t *) = NULL; static int (*fp_lve_leave)(struct liblve *, uint32_t *) = NULL; static int (*fp_lve_jail)( struct passwd *, char *) = NULL; -static int lsapi_load_lve_lib() +static int lsapi_load_lve_lib(void) { s_liblve = dlopen("liblve.so.0", RTLD_LAZY); if (s_liblve) @@ -642,7 +781,8 @@ static int lsapi_load_lve_lib() return (s_liblve)? 0 : -1; } -static int init_lve_ex() + +static int init_lve_ex(void) { int rc; if ( !s_liblve ) @@ -714,7 +854,8 @@ static int readSecret( const char * pSecretFile ) return 0; } -int LSAPI_is_suEXEC_Daemon() + +int LSAPI_is_suEXEC_Daemon(void) { if (( !s_uid )&&( s_secret[0] )) return 1; @@ -722,10 +863,14 @@ int LSAPI_is_suEXEC_Daemon() return 0; } + static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char *pErr2 ) { - char achError[1024]; - int n = snprintf(achError, 1024, "%s:%s: %s\n", pErr1, (pErr2)?pErr2:"", strerror( errno ) ); + char achError[4096]; + int n = snprintf(achError, sizeof(achError), "[%d] %s:%s: %s\n", getpid(), + pErr1, (pErr2)?pErr2:"", strerror(errno)); + if (n > (int)sizeof(achError)) + n = sizeof(achError); if ( pReq ) LSAPI_Write_Stderr_r( pReq, achError, n ); else @@ -733,6 +878,7 @@ static int LSAPI_perror_r( LSAPI_Request * pReq, const char * pErr1, const char return 0; } + static int lsapi_lve_error( LSAPI_Request * pReq ) { static const char * headers[] = @@ -756,6 +902,7 @@ static int lsapi_lve_error( LSAPI_Request * pReq ) return 0; } + static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid ) { #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) @@ -777,6 +924,7 @@ static int lsapi_enterLVE( LSAPI_Request * pReq, uid_t uid ) return 0; } + static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) { int ret = 0; @@ -796,7 +944,7 @@ static int lsapi_jailLVE( LSAPI_Request * pReq, uid_t uid, struct passwd * pw ) #if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__) -static int lsapi_initLVE() +static int lsapi_initLVE(void) { const char * pEnv; if ( (pEnv = getenv( "LSAPI_LVE_ENABLE" ))!= NULL ) @@ -926,7 +1074,8 @@ static int lsapi_changeUGid( LSAPI_Request * pReq ) { int uid = s_defaultUid; int gid = s_defaultGid; - const char * pChroot = NULL; + const char *pStderrLog; + const char *pChroot = NULL; struct LSAPI_key_value_pair * pEnv; struct LSAPI_key_value_pair * pAuth; int i; @@ -991,11 +1140,16 @@ static int lsapi_changeUGid( LSAPI_Request * pReq ) } s_uid = uid; + + pStderrLog = LSAPI_GetEnv_r( pReq, "LSAPI_STDERR_LOG"); + if (pStderrLog) + lsapi_reopen_stderr(pStderrLog); return 0; } + static int parseContentLenFromHeader(LSAPI_Request * pReq) { const char * pContentLen = LSAPI_GetHeader_r( pReq, H_CONTENT_LENGTH ); @@ -1062,8 +1216,8 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen ) pBegin += pReq->m_pHeader->m_httpHeaderLen; if ( pBegin != pEnd ) { - fprintf( stderr, "%d: request header does match total size, total: %d, real: %ld\n", getpid(), totalLen, - pBegin - pReq->m_pReqBuf ); + fprintf( stderr, "%d: request header does match total size, total: %d, " + "real: %ld\n", getpid(), totalLen, pBegin - pReq->m_pReqBuf ); return -1; } if ( shouldFixEndian ) @@ -1086,6 +1240,7 @@ static int parseRequest( LSAPI_Request * pReq, int totalLen ) return 0; } + //OPTIMIZATION static char s_accept_notify = 0; static char s_schedule_notify = 0; @@ -1094,27 +1249,42 @@ static char s_notified_pid = 0; static struct lsapi_packet_header s_ack = {'L', 'S', LSAPI_REQ_RECEIVED, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; +static struct lsapi_packet_header s_conn_close_pkt = {'L', 'S', + LSAPI_CONN_CLOSE, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; + - -static inline int write_req_received_notification( int fd ) +static inline int send_notification_pkt( int fd, struct lsapi_packet_header *pkt ) { - if ( write( fd, &s_ack, LSAPI_PACKET_HEADER_LEN ) - < LSAPI_PACKET_HEADER_LEN ) + if ( write( fd, pkt, LSAPI_PACKET_HEADER_LEN ) < LSAPI_PACKET_HEADER_LEN ) return -1; return 0; } -static void lsapi_sigalarm( int sig ) + +static inline int send_req_received_notification( int fd ) { - if ( s_notify_scheduled ) - { - s_notify_scheduled = 0; - if ( g_req.m_fd != -1 ) - write_req_received_notification( g_req.m_fd ); - } + return send_notification_pkt(fd, &s_ack); } -static inline int lsapi_schedule_notify() + +static inline int send_conn_close_notification( int fd ) +{ + return send_notification_pkt(fd, &s_conn_close_pkt); +} + + +//static void lsapi_sigalarm( int sig ) +//{ +// if ( s_notify_scheduled ) +// { +// s_notify_scheduled = 0; +// if ( g_req.m_fd != -1 ) +// write_req_received_notification( g_req.m_fd ); +// } +//} + + +static inline int lsapi_schedule_notify(void) { if ( !s_notify_scheduled ) { @@ -1124,11 +1294,12 @@ static inline int lsapi_schedule_notify() return 0; } + static inline int notify_req_received( int fd ) { if ( s_schedule_notify ) return lsapi_schedule_notify(); - return write_req_received_notification( fd ); + return send_req_received_notification( fd ); } @@ -1146,6 +1317,7 @@ static inline int lsapi_notify_pid( int fd ) return 0; } + static char s_conn_key_packet[16]; static inline int init_conn_key( int fd ) { @@ -1168,6 +1340,7 @@ static inline int init_conn_key( int fd ) } + static int readReq( LSAPI_Request * pReq ) { int len; @@ -1240,7 +1413,6 @@ static int readReq( LSAPI_Request * pReq ) } - int LSAPI_Init(void) { if ( !g_inited ) @@ -1264,16 +1436,25 @@ int LSAPI_Init(void) return 0; } + void LSAPI_Stop(void) { g_running = 0; } + int LSAPI_IsRunning(void) { return g_running; } + +void LSAPI_Register_Pgrp_Timer_Callback(LSAPI_On_Timer_pf cb) +{ + s_proc_group_timer_cb = cb; +} + + int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) { int newfd; @@ -1312,18 +1493,19 @@ int LSAPI_InitRequest( LSAPI_Request * pReq, int fd ) return 0; } + int LSAPI_Is_Listen( void ) { return LSAPI_Is_Listen_r( &g_req ); } + int LSAPI_Is_Listen_r( LSAPI_Request * pReq) { return pReq->m_fdListen != -1; } - int LSAPI_Accept_r( LSAPI_Request * pReq ) { char achPeer[128]; @@ -1353,6 +1535,10 @@ int LSAPI_Accept_r( LSAPI_Request * pReq ) } else { + if (s_worker_status) + s_worker_status->m_connected = 1; + if (s_busy_workers) + __sync_fetch_and_add(s_busy_workers, 1); lsapi_set_nblock( pReq->m_fd , 0 ); if (((struct sockaddr *)&achPeer)->sa_family == AF_INET ) { @@ -1372,16 +1558,17 @@ int LSAPI_Accept_r( LSAPI_Request * pReq ) if ( !readReq( pReq ) ) break; //abort(); - lsapi_close( pReq->m_fd ); - pReq->m_fd = -1; + lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return 0; } + static struct lsapi_packet_header finish = {'L', 'S', LSAPI_RESP_END, LSAPI_ENDIAN, {LSAPI_PACKET_HEADER_LEN} }; + int LSAPI_Finish_r( LSAPI_Request * pReq ) { /* finish req body */ @@ -1454,6 +1641,7 @@ char * LSAPI_GetHeader_r( LSAPI_Request * pReq, int headerIndex ) return pReq->m_pHttpHeader + off; } + static int readBodyToReqBuf( LSAPI_Request * pReq ) { off_t bodyLeft; @@ -1490,7 +1678,6 @@ int LSAPI_ReqBodyGetChar_r( LSAPI_Request * pReq ) } - int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, int *getLF ) { ssize_t len; @@ -1499,7 +1686,7 @@ int LSAPI_ReqBodyGetLine_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen, in char * pBufCur = pBuf; char * pCur; char * p; - if (!pReq || (pReq->m_fd ==-1) ||( !pBuf )||(bufLen < 0 )|| !getLF ) + if (!pReq || pReq->m_fd == -1 || !pBuf || !getLF) return -1; *getLF = 0; while( (left = pBufEnd - pBufCur ) > 0 ) @@ -1543,21 +1730,21 @@ ssize_t LSAPI_ReadReqBody_r( LSAPI_Request * pReq, char * pBuf, size_t bufLen ) ssize_t len; off_t total; /* char *pOldBuf = pBuf; */ - if (!pReq || (pReq->m_fd ==-1) || ( !pBuf )||(bufLen < 0 )) + if (!pReq || pReq->m_fd == -1 || !pBuf || (ssize_t)bufLen < 0) return -1; total = pReq->m_reqBodyLen - pReq->m_reqBodyRead; if ( total <= 0 ) return 0; - if ( total < bufLen ) + if ( total < (ssize_t)bufLen ) bufLen = total; total = 0; len = pReq->m_bufRead - pReq->m_bufProcessed; if ( len > 0 ) { - if ( len > bufLen ) + if ( len > (ssize_t)bufLen ) len = bufLen; memmove( pBuf, pReq->m_pReqBuf + pReq->m_bufProcessed, len ); pReq->m_bufProcessed += len; @@ -1615,7 +1802,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) } pReq->m_reqState |= LSAPI_ST_RESP_BODY; - if ( (len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) + if ( ((ssize_t)len - skip) < pReq->m_pRespBufEnd - pReq->m_pRespBufPos ) { memmove( pReq->m_pRespBufPos, pBuf + skip, len - skip ); pReq->m_pRespBufPos += len - skip; @@ -1672,6 +1859,7 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len ) return p - pBuf; } + #if defined(__FreeBSD__ ) || defined(__NetBSD__) || defined(__OpenBSD__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { @@ -1687,6 +1875,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) } #endif + #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) { @@ -1702,6 +1891,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t* off, size_t size ) } #endif + #if defined(sun) || defined(__sun) #include <sys/sendfile.h> ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) @@ -1725,11 +1915,14 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t *off, size_t size ) } #endif + #if defined(linux) || defined(__linux) || defined(__linux__) || \ defined(__gnu_linux__) #include <sys/sendfile.h> #define gsendfile sendfile #endif + + #if defined(HPUX) ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size ) { @@ -1737,6 +1930,7 @@ ssize_t gsendfile( int fdOut, int fdIn, off_t * off, size_t size ) } #endif + ssize_t LSAPI_sendfile_r( LSAPI_Request * pReq, int fdIn, off_t* off, size_t size ) { struct lsapi_packet_header * pHeader = pReq->m_respPktHeader; @@ -1785,8 +1979,6 @@ void Flush_RespBuf_r( LSAPI_Request * pReq ) } - - int LSAPI_Flush_r( LSAPI_Request * pReq ) { int ret = 0; @@ -1820,8 +2012,7 @@ int LSAPI_Flush_r( LSAPI_Request * pReq ) n, pReq->m_totalLen ); if ( ret < pReq->m_totalLen ) { - lsapi_close( pReq->m_fd ); - pReq->m_fd = -1; + lsapi_close_connection(pReq); ret = -1; } pReq->m_totalLen = 0; @@ -1844,7 +2035,7 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le if ( !pReq ) return -1; - if (( pReq->m_fd == -1 )||(pReq->m_fd == pReq->m_fdListen )) + if (s_stderr_log_path || pReq->m_fd == -1 || pReq->m_fd == pReq->m_fdListen) return write( 2, pBuf, len ); if ( pReq->m_pRespBufPos != pReq->m_pRespBuf ) { @@ -1876,14 +2067,14 @@ ssize_t LSAPI_Write_Stderr_r( LSAPI_Request * pReq, const char * pBuf, size_t le 2, totalLen ); if ( ret < totalLen ) { - lsapi_close( pReq->m_fd ); - pReq->m_fd = -1; + lsapi_close_connection(pReq); ret = -1; } } return p - pBuf; } + static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) { int i; @@ -1963,6 +2154,7 @@ char * LSAPI_GetEnv_r( LSAPI_Request * pReq, const char * name ) return NULL; } + struct _headerInfo { const char * _name; @@ -1971,12 +2163,14 @@ struct _headerInfo int _valueLen; }; + int compareValueLocation(const void * v1, const void *v2 ) { return ((const struct _headerInfo *)v1)->_value - ((const struct _headerInfo *)v2)->_value; } + int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { @@ -2050,7 +2244,6 @@ int LSAPI_ForeachOrgHeader_r( LSAPI_Request * pReq, return ret; } return count; - } @@ -2119,9 +2312,9 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, } } return count + pReq->m_pHeader->m_cntUnknownHeaders; - } + static int EnvForeach( struct LSAPI_key_value_pair * pEnv, int n, LSAPI_CB_EnvHandler fn, void * arg ) { @@ -2141,7 +2334,6 @@ static int EnvForeach( struct LSAPI_key_value_pair * pEnv, } - int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { @@ -2156,7 +2348,6 @@ int LSAPI_ForeachEnv_r( LSAPI_Request * pReq, } - int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, LSAPI_CB_EnvHandler fn, void * arg ) { @@ -2173,7 +2364,6 @@ int LSAPI_ForeachSpecialEnv_r( LSAPI_Request * pReq, } - int LSAPI_FinalizeRespHeaders_r( LSAPI_Request * pReq ) { if ( !pReq || !pReq->m_pIovec ) @@ -2257,7 +2447,6 @@ int LSAPI_AppendRespHeader2_r( LSAPI_Request * pReq, const char * pHeaderName, } - int LSAPI_AppendRespHeader_r( LSAPI_Request * pReq, const char * pBuf, int len ) { if ( !pReq || !pBuf || len <= 0 || len > LSAPI_RESP_HTTP_HEADER_MAX ) @@ -2338,9 +2527,9 @@ int LSAPI_CreateListenSock2( const struct sockaddr * pServerAddr, int backlog ) close(fd); errno = ret; return -1; - } + int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) { char achAddr[256]; @@ -2438,6 +2627,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) } + int LSAPI_CreateListenSock( const char * pBind, int backlog ) { char serverAddr[128]; @@ -2451,25 +2641,8 @@ int LSAPI_CreateListenSock( const char * pBind, int backlog ) return fd; } -static fn_select_t g_fnSelect = select; - -typedef struct _lsapi_child_status -{ - int m_pid; - long m_tmStart; - - volatile short m_iKillSent; - volatile short m_inProcess; - volatile int m_iReqCounter; - - volatile long m_tmWaitBegin; - volatile long m_tmReqBegin; - volatile long m_tmLastCheckPoint; -} -lsapi_child_status; - -static lsapi_child_status * s_pChildStatus = NULL; +static fn_select_t g_fnSelect = select; typedef struct _lsapi_prefork_server { int m_fd; @@ -2487,12 +2660,11 @@ typedef struct _lsapi_prefork_server lsapi_child_status * m_pChildrenStatusEnd; }lsapi_prefork_server; - static lsapi_prefork_server * g_prefork_server = NULL; + int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) { - int pid; if ( g_prefork_server ) return 0; if ( max_children <= 1 ) @@ -2500,6 +2672,8 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) if ( max_children >= 10000) max_children = 10000; + if (s_max_busy_workers == 0) + s_max_busy_workers = max_children / 2 + 1; g_prefork_server = (lsapi_prefork_server *)malloc( sizeof( lsapi_prefork_server ) ); if ( !g_prefork_server ) @@ -2510,8 +2684,8 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) g_fnSelect = fp; s_ppid = getppid(); - pid = getpid(); - setpgid( pid, pid ); + s_pid = getpid(); + setpgid( s_pid, s_pid ); g_prefork_server->m_iAvoidFork = avoidFork; g_prefork_server->m_iMaxChildren = max_children; @@ -2524,6 +2698,7 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork ) return 0; } + void LSAPI_Set_Server_fd( int fd ) { if( g_prefork_server ) @@ -2557,12 +2732,8 @@ static int lsapi_accept( int fdListen ) } - - -static int s_req_processed = 0; -static int s_max_reqs = 10000; +static unsigned int s_max_reqs = UINT_MAX; static int s_max_idle_secs = 300; - static int s_stop; static void lsapi_cleanup(int signal) @@ -2570,6 +2741,7 @@ static void lsapi_cleanup(int signal) s_stop = signal; } + static lsapi_child_status * find_child_status( int pid ) { lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; @@ -2588,11 +2760,33 @@ static lsapi_child_status * find_child_status( int pid ) } +void LSAPI_reset_server_state( void ) +{ + /* + Reset child status + */ + g_prefork_server->m_iCurChildren = 0; + lsapi_child_status * pStatus = g_prefork_server->m_pChildrenStatus; + lsapi_child_status * pEnd = g_prefork_server->m_pChildrenStatusEnd; + while( pStatus < pEnd ) + { + pStatus->m_pid = 0; + ++pStatus; + } + if (s_busy_workers) + __sync_lock_release(s_busy_workers); + if (s_accepting_workers) + __sync_lock_release(s_accepting_workers); + +} + static void lsapi_sigchild( int signal ) { int status, pid; lsapi_child_status * child_status; + if (g_prefork_server == NULL) + return; while( 1 ) { pid = waitpid( -1, &status, WNOHANG|WUNTRACED ); @@ -2604,7 +2798,8 @@ static void lsapi_sigchild( int signal ) { int sig_num = WTERMSIG( status ); int dump = WCOREDUMP( status ); - fprintf( stderr, "Child process with pid: %d was killed by signal: %d, core dump: %d\n", pid, sig_num, dump ); + fprintf( stderr, "Child process with pid: %d was killed by signal: " + "%d, core dump: %d\n", pid, sig_num, dump ); } if ( pid == s_pid_dump_debug_info ) { @@ -2614,9 +2809,14 @@ static void lsapi_sigchild( int signal ) child_status = find_child_status( pid ); if ( child_status ) { + if (child_status->m_connected) + { + if (s_busy_workers) + __sync_fetch_and_sub(s_busy_workers, 1); + child_status->m_connected = 0; + } child_status->m_pid = 0; --g_prefork_server->m_iCurChildren; - } } while(( g_prefork_server->m_pChildrenStatusCur > g_prefork_server->m_pChildrenStatus ) @@ -2625,13 +2825,16 @@ static void lsapi_sigchild( int signal ) } -static int lsapi_init_children_status() + +static int lsapi_init_children_status(void) { int size = 4096; - + int max_children = g_prefork_server->m_iMaxChildren + + g_prefork_server->m_iExtraChildren; + char * pBuf; - size = (g_prefork_server->m_iMaxChildren + g_prefork_server->m_iExtraChildren ) * sizeof( lsapi_child_status ) * 2; - size = (size + 4095 ) / 4096 * 4096; + size = max_children * sizeof( lsapi_child_status ) * 2 + 3 * sizeof(int); + size = (size + 4095) / 4096 * 4096; pBuf =( char*) mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0 ); if ( pBuf == MAP_FAILED ) @@ -2639,12 +2842,17 @@ static int lsapi_init_children_status() perror( "Anonymous mmap() failed" ); return -1; } + memset( pBuf, 0, size ); g_prefork_server->m_pChildrenStatus = (lsapi_child_status *)pBuf; g_prefork_server->m_pChildrenStatusCur = (lsapi_child_status *)pBuf; - g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + size / sizeof( lsapi_child_status ); + g_prefork_server->m_pChildrenStatusEnd = (lsapi_child_status *)pBuf + max_children; + s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd; + s_accepting_workers = s_busy_workers + 1; + s_global_counter = s_accepting_workers + 1; return 0; } + static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) { char achCmd[1024]; @@ -2655,15 +2863,20 @@ static void dump_debug_info( lsapi_child_status * pStatus, long tmCur ) } s_pid_dump_debug_info = fork(); - fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, reqCount: %d, process time: %ld, checkpoint time: %ld, start time: %ld\n", - ctime(&tmCur), getpid(), pStatus->m_pid, pStatus->m_iReqCounter, - tmCur - pStatus->m_tmReqBegin, tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); - snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" -ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", pStatus->m_pid, pStatus->m_pid ); + fprintf( stderr, "[%s] Possible runaway process, PPID: %d, PID: %d, " + "reqCount: %d, process time: %ld, checkpoint time: %ld, start " + "time: %ld\n", ctime(&tmCur), getpid(), pStatus->m_pid, + pStatus->m_iReqCounter, tmCur - pStatus->m_tmReqBegin, + tmCur - pStatus->m_tmLastCheckPoint, tmCur - pStatus->m_tmStart ); + snprintf( achCmd, 1024, "gdb --batch -ex \"attach %d\" -ex \"set height 0\" " + "-ex \"bt\" >&2;PATH=$PATH:/usr/sbin lsof -p %d >&2", + pStatus->m_pid, pStatus->m_pid ); if ( system( achCmd ) == -1 ) perror( "system()" ); exit( 0 ); } + static void lsapi_check_child_status( long tmCur ) { int idle = 0; @@ -2681,15 +2894,17 @@ static void lsapi_check_child_status( long tmCur ) if ( !pStatus->m_inProcess ) { - if (( g_prefork_server->m_iCurChildren - dying > g_prefork_server->m_iMaxChildren)|| - ( idle > g_prefork_server->m_iMaxIdleChildren )) + if (g_prefork_server->m_iCurChildren - dying + > g_prefork_server->m_iMaxChildren + || idle > g_prefork_server->m_iMaxIdleChildren) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; } else { - if (( s_max_idle_secs> 0)&&(tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5 )) + if (s_max_idle_secs> 0 + && tmCur - pStatus->m_tmWaitBegin > s_max_idle_secs + 5) { ++pStatus->m_iKillSent; //tobekilled = SIGUSR1; @@ -2700,26 +2915,29 @@ static void lsapi_check_child_status( long tmCur ) } else { - if ( tmCur - pStatus->m_tmReqBegin > - g_prefork_server->m_iMaxReqProcessTime ) + if (tmCur - pStatus->m_tmReqBegin > + g_prefork_server->m_iMaxReqProcessTime) { - if (( ( pStatus->m_iKillSent % 5 ) == 0 )&&( s_dump_debug_info )) + if ((pStatus->m_iKillSent % 5) == 0 && s_dump_debug_info) dump_debug_info( pStatus, tmCur ); if ( pStatus->m_iKillSent > 5 ) { tobekilled = SIGKILL; - fprintf( stderr, "Force killing runaway process PID: %d with SIGKILL\n", pStatus->m_pid ); + fprintf( stderr, "Force killing runaway process PID: %d" + " with SIGKILL\n", pStatus->m_pid ); } else { tobekilled = SIGTERM; - fprintf( stderr, "Killing runaway process PID: %d with SIGTERM\n", pStatus->m_pid ); + fprintf( stderr, "Killing runaway process PID: %d with " + "SIGTERM\n", pStatus->m_pid ); } } } if ( tobekilled ) { - if (( kill( pStatus->m_pid, tobekilled ) == -1 )&&( errno == ESRCH )) + if (( kill( pStatus->m_pid, tobekilled ) == -1 ) && + ( errno == ESRCH )) { pStatus->m_pid = 0; --count; @@ -2735,34 +2953,35 @@ static void lsapi_check_child_status( long tmCur ) } if ( abs( g_prefork_server->m_iCurChildren - count ) > 1 ) { - fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d, count: %d, idle: %d, dying: %d\n", getpid(), - g_prefork_server->m_iCurChildren, count, idle, dying ); - + fprintf( stderr, "Children tracking is wrong: PID: %d, Cur Children: %d," + " count: %d, idle: %d, dying: %d\n", getpid(), + g_prefork_server->m_iCurChildren, count, idle, dying ); } } -static int lsapi_all_children_must_die() -{ - int maxWait; - int sec =0; - g_prefork_server->m_iMaxReqProcessTime = 10; - g_prefork_server->m_iMaxIdleChildren = -1; - maxWait = 15; - while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) - { - lsapi_check_child_status(time(NULL)); - sleep( 1 ); - sec++; - } - if ( g_prefork_server->m_iCurChildren != 0 ) - kill( -getpgrp(), SIGKILL ); - return 0; -} +//static int lsapi_all_children_must_die(void) +//{ +// int maxWait; +// int sec =0; +// g_prefork_server->m_iMaxReqProcessTime = 10; +// g_prefork_server->m_iMaxIdleChildren = -1; +// maxWait = 15; +// +// while( g_prefork_server->m_iCurChildren && (sec < maxWait) ) +// { +// lsapi_check_child_status(time(NULL)); +// sleep( 1 ); +// sec++; +// } +// if ( g_prefork_server->m_iCurChildren != 0 ) +// kill( -getpgrp(), SIGKILL ); +// return 0; +//} - -static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Request * pReq ) +static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, + LSAPI_Request * pReq ) { struct sigaction act, old_term, old_quit, old_int, old_usr1, old_child; @@ -2804,11 +3023,15 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re s_stop = 0; while( !s_stop ) { + if (s_proc_group_timer_cb != NULL) { + s_proc_group_timer_cb(); + } + curTime = time( NULL ); if (curTime != lastTime ) { lastTime = curTime; - if (s_ppid && (getppid() != s_ppid )) + if (lsapi_parent_dead()) break; lsapi_check_child_status(curTime ); if (pServer->m_iServerMaxIdle) @@ -2824,29 +3047,20 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re } } - if ( pServer->m_iCurChildren >= (pServer->m_iMaxChildren + pServer->m_iExtraChildren ) ) - { - fprintf( stderr, "Reached max children process limit: %d, extra: %d, current: %d, please increase LSAPI_CHILDREN.\n", - pServer->m_iMaxChildren, pServer->m_iExtraChildren, pServer->m_iCurChildren ); - usleep( 100000 ); - continue; - } - FD_ZERO( &readfds ); FD_SET( pServer->m_fd, &readfds ); - timeout.tv_sec = 1; timeout.tv_usec = 0; - if ((ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout)) == 1 ) - { - /* - if ( pServer->m_iCurChildren >= 0 ) + timeout.tv_sec = 1; + timeout.tv_usec = 0; + ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout); + if (ret == 1 ) + { + if (pServer->m_iCurChildren >= pServer->m_iMaxChildren + && s_accepting_workers + && (ret = __sync_add_and_fetch(s_accepting_workers, 0)) > 0) { - usleep( 10 ); - FD_ZERO( &readfds ); - FD_SET( pServer->m_fd, &readfds ); - timeout.tv_sec = 0; timeout.tv_usec = 0; - if ( (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout) == 0 ) - continue; - }*/ + usleep( 200 ); + continue; + } } else if ( ret == -1 ) { @@ -2860,6 +3074,18 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re continue; } + if (pServer->m_iCurChildren >= + pServer->m_iMaxChildren + pServer->m_iExtraChildren) + { + fprintf( stderr, "Reached max children process limit: %d, extra: %d," + " current: %d, busy: %d, please increase LSAPI_CHILDREN.\n", + pServer->m_iMaxChildren, pServer->m_iExtraChildren, + pServer->m_iCurChildren, + s_busy_workers ? *s_busy_workers : -1 ); + usleep( 100000 ); + continue; + } + pReq->m_fd = lsapi_accept( pServer->m_fd ); if ( pReq->m_fd != -1 ) { @@ -2879,18 +3105,27 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re if ( !pid ) { + setsid(); if (sigprocmask(SIG_SETMASK, &orig_mask, NULL) < 0) perror( "sigprocmask( SIG_SETMASK ) to restore SIGMASK in child" ); g_prefork_server = NULL; s_ppid = getppid(); + s_pid = getpid(); s_req_processed = 0; - s_pChildStatus = child_status; + s_proc_group_timer_cb = NULL; + s_worker_status = child_status; + + s_worker_status->m_connected = 1; + if (s_busy_workers) + __sync_add_and_fetch(s_busy_workers, 1); lsapi_set_nblock( pReq->m_fd, 0 ); - if ( pReq->m_fdListen != -1 ) - { - close( pReq->m_fdListen ); - pReq->m_fdListen = -1; - } + //keep it open if busy_count is used. + s_keepListener = 1; +// if ( pReq->m_fdListen != -1 ) +// { +// close( pReq->m_fdListen ); +// pReq->m_fdListen = -1; +// } /* don't catch our signals */ sigaction( SIGCHLD, &old_child, 0 ); sigaction( SIGTERM, &old_term, 0 ); @@ -2940,11 +3175,14 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer, LSAPI_Re } + void lsapi_error( const char * pMessage, int err_no ) { - fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, strerror( err_no ) ); + fprintf( stderr, "%d: %s, errno: %d (%s)\n", getpid(), pMessage, err_no, + strerror( err_no ) ); } + int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) { int fd; @@ -2955,19 +3193,28 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) LSAPI_Finish_r( pReq ); - if ( g_prefork_server ) { if ( g_prefork_server->m_fd != -1 ) if ( lsapi_prefork_server_accept( g_prefork_server, pReq ) == -1 ) return -1; } - if ( s_req_processed >= s_max_reqs ) + else if (s_req_processed > 0 && s_max_busy_workers > 0 && s_busy_workers) + { + ret = __sync_fetch_and_add(s_busy_workers, 0); + if (ret >= s_max_busy_workers) + { + send_conn_close_notification(pReq->m_fd); + lsapi_close_connection(pReq); + } + } + + if ( (unsigned int)s_req_processed > s_max_reqs ) return -1; - if ( s_pChildStatus ) + if ( s_worker_status ) { - s_pChildStatus->m_tmWaitBegin = time( NULL ); + s_worker_status->m_tmWaitBegin = time( NULL ); } @@ -2988,23 +3235,37 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) { if ( !g_running ) return -1; - if ((s_req_processed)&&( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) + if (s_req_processed && s_worker_status + && s_worker_status->m_iKillSent) return -1; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); timeout.tv_sec = 1; timeout.tv_usec = 0; + if (fd == pReq->m_fdListen) + { + if (s_accepting_workers) + __sync_fetch_and_add(s_accepting_workers, 1); + } ret = (*g_fnSelect)(fd+1, &readfds, NULL, NULL, &timeout); + if (fd == pReq->m_fdListen) + { + if (s_accepting_workers) + __sync_fetch_and_sub(s_accepting_workers, 1); + } + if ( ret == 0 ) { - if ( s_pChildStatus ) + if ( s_worker_status ) { - s_pChildStatus->m_inProcess = 0; + s_worker_status->m_inProcess = 0; + if (fd == pReq->m_fdListen) + return -1; } ++wait_secs; if (( s_max_idle_secs > 0 )&&(wait_secs >= s_max_idle_secs )) return -1; - if ( s_ppid &&( getppid() != s_ppid)) + if ( lsapi_parent_dead() ) return -1; } else if ( ret == -1 ) @@ -3016,14 +3277,21 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) } else if ( ret >= 1 ) { - if (s_req_processed && ( s_pChildStatus )&&( s_pChildStatus->m_iKillSent )) + if (s_req_processed && s_worker_status + && s_worker_status->m_iKillSent) return -1; if ( fd == pReq->m_fdListen ) { pReq->m_fd = lsapi_accept( pReq->m_fdListen ); if ( pReq->m_fd != -1 ) { + if (s_worker_status) + s_worker_status->m_connected = 1; + if (s_busy_workers) + __sync_fetch_and_add(s_busy_workers, 1); + fd = pReq->m_fd; + lsapi_set_nblock( fd, 0 ); //init_conn_key( pReq->m_fd ); if ( !s_keepListener ) @@ -3050,42 +3318,46 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq ) if ( !readReq( pReq ) ) { - if ( s_pChildStatus ) + if ( s_worker_status ) { - s_pChildStatus->m_iKillSent = 0; - s_pChildStatus->m_inProcess = 1; - ++s_pChildStatus->m_iReqCounter; - s_pChildStatus->m_tmReqBegin = s_pChildStatus->m_tmLastCheckPoint = time(NULL); + s_worker_status->m_iKillSent = 0; + s_worker_status->m_inProcess = 1; + ++s_worker_status->m_iReqCounter; + s_worker_status->m_tmReqBegin = + s_worker_status->m_tmLastCheckPoint = time(NULL); } ++s_req_processed; return 0; } - lsapi_close( pReq->m_fd ); - pReq->m_fd = -1; + lsapi_close_connection(pReq); LSAPI_Reset_r( pReq ); } return -1; } + void LSAPI_Set_Max_Reqs( int reqs ) -{ s_max_reqs = reqs; } +{ s_max_reqs = reqs - 1; } void LSAPI_Set_Max_Idle( int secs ) { s_max_idle_secs = secs; } + void LSAPI_Set_Max_Children( int maxChildren ) { if ( g_prefork_server ) g_prefork_server->m_iMaxChildren = maxChildren; } + void LSAPI_Set_Extra_Children( int extraChildren ) { if (( g_prefork_server )&&( extraChildren >= 0 )) g_prefork_server->m_iExtraChildren = extraChildren; } + void LSAPI_Set_Max_Process_Time( int secs ) { if (( g_prefork_server )&&( secs > 0 )) @@ -3099,34 +3371,44 @@ void LSAPI_Set_Max_Idle_Children( int maxIdleChld ) g_prefork_server->m_iMaxIdleChildren = maxIdleChld; } + void LSAPI_Set_Server_Max_Idle_Secs( int serverMaxIdle ) { if ( g_prefork_server ) g_prefork_server->m_iServerMaxIdle = serverMaxIdle; } + void LSAPI_Set_Slow_Req_Msecs( int msecs ) { s_slow_req_msecs = msecs; } -int LSAPI_Get_Slow_Req_Msecs() + +int LSAPI_Get_Slow_Req_Msecs(void) { return s_slow_req_msecs; } -void LSAPI_No_Check_ppid() +void LSAPI_No_Check_ppid(void) { s_ppid = 0; } + +int LSAPI_Get_ppid() +{ + return(s_ppid); +} + + #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) #include <crt_externs.h> #else extern char ** environ; #endif -static void unset_lsapi_envs() +static void unset_lsapi_envs(void) { char **env; #if defined(macintosh) || defined(__APPLE__) || defined(__APPLE_CC__) @@ -3149,7 +3431,8 @@ static void unset_lsapi_envs() } } -static int lsapi_initSuEXEC() + +static int lsapi_initSuEXEC(void) { int i; struct passwd * pw; @@ -3204,11 +3487,88 @@ static int lsapi_initSuEXEC() } +static int lsapi_check_path(const char *p, char *final, int max_len) +{ + char resolved_path[PATH_MAX+1]; + int len = 0; + char *end; + if (*p != '/') + { + if (getcwd(final, max_len) == NULL) + return -1; + len = strlen(final); + *(final + len) = '/'; + ++len; + } + end = memccpy(&final[len], p, '\0', PATH_MAX - len); + if (!end) + { + errno = EINVAL; + return -1; + } + p = final; + if (realpath(p, resolved_path) == NULL + && errno != ENOENT && errno != EACCES) + return -1; + if (strncmp(resolved_path, "/etc/", 5) == 0) + { + errno = EPERM; + return -1; + } + return 0; +} + + +static int lsapi_reopen_stderr2(const char *full_path) +{ + int newfd = open(full_path, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (newfd == -1) + { + LSAPI_perror_r(NULL, "failed to open custom stderr log", full_path); + return -1; + } + if (newfd != 2) + { + dup2(newfd, 2); + close(newfd); + dup2(2, 1); + } + if (s_stderr_log_path && full_path != s_stderr_log_path) + { + free(s_stderr_log_path); + s_stderr_log_path = NULL; + } + s_stderr_log_path = strdup(full_path); + return 0; +} + + +static int lsapi_reopen_stderr(const char *p) +{ + char full_path[PATH_MAX]; + if (s_uid == 0) + return -1; + if (lsapi_check_path(p, full_path, PATH_MAX) == -1) + { + LSAPI_perror_r(NULL, "invalid custom stderr log path", p); + return -1; + } + return lsapi_reopen_stderr2(full_path); +} + + int LSAPI_Init_Env_Parameters( fn_select_t fp ) { const char *p; int n; int avoidFork = 0; + + p = getenv("LSAPI_STDERR_LOG"); + if (p) + { + lsapi_reopen_stderr(p); + } + p = getenv( "PHP_LSAPI_MAX_REQUESTS" ); if ( !p ) p = getenv( "LSAPI_MAX_REQS" ); @@ -3301,6 +3661,16 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp ) { LSAPI_No_Check_ppid(); } + + p = getenv("LSAPI_MAX_BUSY_WORKER"); + if (p) + { + n = atoi(p); + s_max_busy_workers = n; + if (n >= 0) + LSAPI_No_Check_ppid(); + } + p = getenv( "LSAPI_DUMP_DEBUG_INFO" ); if ( p ) @@ -3354,6 +3724,7 @@ static void byteReverse(unsigned char *buf, unsigned longs) } while (--longs); } + /* * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious * initialization constants. @@ -3417,6 +3788,7 @@ void lsapi_MD5Update(struct lsapi_MD5Context *ctx, unsigned char const *buf, uns memmove(ctx->in, buf, len); } + /* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) @@ -3462,6 +3834,7 @@ void lsapi_MD5Final(unsigned char digest[16], struct lsapi_MD5Context *ctx) memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ } + /* The four core functions - F1 is optimized somewhat */ /* #define F1(x, y, z) (x & y | ~x & z) */ @@ -3562,3 +3935,18 @@ static void lsapi_MD5Transform(uint32 buf[4], uint32 const in[16]) buf[3] += d; } + +int LSAPI_Set_Restored_Parent_Pid(int pid) +{ + int old_ppid = s_ppid; + s_restored_ppid = pid; + return old_ppid; +} + + +int LSAPI_Inc_Req_Processed(int cnt) +{ + return __sync_add_and_fetch(s_global_counter, cnt); +} + + |