summaryrefslogtreecommitdiff
path: root/sapi/litespeed/lsapilib.c
diff options
context:
space:
mode:
authorGeorge Wang <gwang@php.net>2018-02-27 13:54:28 -0500
committerGeorge Wang <gwang@php.net>2018-02-27 13:54:28 -0500
commit97ff815cbbfe524a46ab5e76312d19a4b3771079 (patch)
tree86247f316a8dcc8783f6e38216f906090a02a23d /sapi/litespeed/lsapilib.c
parentea4ba9d008d4b3953dcd74a69d2f2b6aa620fd81 (diff)
downloadphp-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.c724
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);
+}
+
+