LiteSpeed SAPI 7.3, better process management, new API function litespeed_finish_request().

This commit is contained in:
George Wang 2019-04-12 17:43:45 -04:00
parent d07a6fdedf
commit 1e7f1b90e8
3 changed files with 152 additions and 26 deletions

View File

@ -466,7 +466,7 @@ static int sapi_lsapi_activate()
static sapi_module_struct lsapi_sapi_module =
{
"litespeed",
"LiteSpeed V7.2",
"LiteSpeed V7.3",
php_lsapi_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
@ -1394,6 +1394,7 @@ ZEND_END_ARG_INFO()
PHP_FUNCTION(litespeed_request_headers);
PHP_FUNCTION(litespeed_response_headers);
PHP_FUNCTION(apache_get_modules);
PHP_FUNCTION(litespeed_finish_request);
PHP_MINFO_FUNCTION(litespeed);
@ -1401,9 +1402,11 @@ zend_function_entry litespeed_functions[] = {
PHP_FE(litespeed_request_headers, arginfo_litespeed__void)
PHP_FE(litespeed_response_headers, arginfo_litespeed__void)
PHP_FE(apache_get_modules, arginfo_litespeed__void)
PHP_FE(litespeed_finish_request, arginfo_litespeed__void)
PHP_FALIAS(getallheaders, litespeed_request_headers, arginfo_litespeed__void)
PHP_FALIAS(apache_request_headers, litespeed_request_headers, arginfo_litespeed__void)
PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void)
PHP_FALIAS(fastcgi_finish_request, litespeed_finish_request, arginfo_litespeed__void)
{NULL, NULL, NULL}
};
@ -1532,6 +1535,20 @@ PHP_FUNCTION(apache_get_modules)
/* }}} */
/* {{{ proto array litespeed_finish_request(void)
Flushes all response data to the client */
PHP_FUNCTION(litespeed_finish_request)
{
if (ZEND_NUM_ARGS() > 0) {
WRONG_PARAM_COUNT;
}
if (LSAPI_End_Response() != -1) {
RETURN_TRUE;
}
RETURN_FALSE;
}
/* }}} */
/*
* Local variables:
* tab-width: 4

View File

@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <fcntl.h>
#include <limits.h>
#include <sys/stat.h>
#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
@ -113,10 +114,18 @@ typedef struct lsapi_MD5Context lsapi_MD5_CTX;
#define LSAPI_ST_REQ_BODY 2
#define LSAPI_ST_RESP_HEADER 4
#define LSAPI_ST_RESP_BODY 8
#define LSAPI_ST_BACKGROUND 16
#define LSAPI_RESP_BUF_SIZE 8192
#define LSAPI_INIT_RESP_HEADER_LEN 4096
enum
{
LSAPI_STATE_IDLE,
LSAPI_STATE_CONNECTED,
LSAPI_STATE_ACCEPTING,
};
typedef struct _lsapi_child_status
{
int m_pid;
@ -124,7 +133,7 @@ typedef struct _lsapi_child_status
volatile short m_iKillSent;
volatile char m_inProcess;
volatile char m_connected;
volatile char m_state;
volatile int m_iReqCounter;
volatile long m_tmWaitBegin;
@ -156,6 +165,9 @@ static int s_max_busy_workers = -1;
static char *s_stderr_log_path = NULL;
static int s_stderr_is_pipe = 0;
static int s_ignore_pid = -1;
static size_t s_total_pages = 1;
static size_t s_min_avail_pages = 256 * 1024;
static size_t *s_avail_pages = &s_total_pages;
LSAPI_Request g_req =
{ .m_fdListen = -1, .m_fd = -1 };
@ -415,7 +427,7 @@ static void lsapi_close_connection(LSAPI_Request *pReq)
if (s_busy_workers)
__sync_fetch_and_sub(s_busy_workers, 1);
if (s_worker_status)
s_worker_status->m_connected = 0;
__sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
}
@ -1558,7 +1570,8 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
else
{
if (s_worker_status)
s_worker_status->m_connected = 1;
__sync_lock_test_and_set(&s_worker_status->m_state,
LSAPI_STATE_CONNECTED);
if (s_busy_workers)
__sync_fetch_and_add(s_busy_workers, 1);
lsapi_set_nblock( pReq->m_fd , 0 );
@ -1621,6 +1634,37 @@ int LSAPI_Finish_r( LSAPI_Request * pReq )
}
int LSAPI_End_Response_r(LSAPI_Request * pReq)
{
if (!pReq)
return -1;
if (pReq->m_reqState)
{
if ( pReq->m_fd != -1 )
{
if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
{
LSAPI_FinalizeRespHeaders_r( pReq );
}
if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
{
Flush_RespBuf_r( pReq );
}
pReq->m_pIovecCur->iov_base = (void *)&finish;
pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
++pReq->m_pIovecCur;
LSAPI_Flush_r( pReq );
}
send_conn_close_notification(pReq->m_fd);
lsapi_close_connection(pReq);
pReq->m_reqState |= LSAPI_ST_BACKGROUND;
}
return 0;
}
void LSAPI_Reset_r( LSAPI_Request * pReq )
{
pReq->m_pRespBufPos = pReq->m_pRespBuf;
@ -1806,7 +1850,11 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
ssize_t packetLen;
int skip = 0;
if ( !pReq || !pBuf || (pReq->m_fd == -1) )
if (!pReq || !pBuf)
return -1;
if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
return len;
if (pReq->m_fd == -1)
return -1;
if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
{
@ -2708,6 +2756,9 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
s_ppid = getppid();
s_pid = getpid();
setpgid( s_pid, s_pid );
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
s_total_pages = sysconf(_SC_PHYS_PAGES);
#endif
g_prefork_server->m_iAvoidFork = avoidFork;
g_prefork_server->m_iMaxChildren = max_children;
@ -2842,11 +2893,19 @@ static void lsapi_sigchild( int signal )
child_status = find_child_status( pid );
if ( child_status )
{
if (child_status->m_connected)
if (__sync_bool_compare_and_swap(&child_status->m_state,
LSAPI_STATE_CONNECTED,
LSAPI_STATE_IDLE))
{
if (s_busy_workers)
__sync_fetch_and_sub(s_busy_workers, 1);
child_status->m_connected = 0;
}
else if (__sync_bool_compare_and_swap(&child_status->m_state,
LSAPI_STATE_ACCEPTING,
LSAPI_STATE_IDLE))
{
if (s_accepting_workers)
__sync_fetch_and_sub(s_accepting_workers, 1);
}
child_status->m_pid = 0;
--g_prefork_server->m_iCurChildren;
@ -2882,6 +2941,7 @@ static int lsapi_init_children_status(void)
s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
s_accepting_workers = s_busy_workers + 1;
s_global_counter = s_accepting_workers + 1;
s_avail_pages = (size_t *)(s_global_counter + 1);
return 0;
}
@ -3021,6 +3081,17 @@ void set_skip_write()
{ s_skip_write = 1; }
int is_enough_free_mem()
{
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
//minimum 1GB or 10% available free memory
return (*s_avail_pages > s_min_avail_pages
|| (*s_avail_pages * 10) / s_total_pages > 0);
#endif
return 1;
}
static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
LSAPI_Request * pReq )
{
@ -3090,6 +3161,12 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
}
}
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
*s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
#endif
FD_ZERO( &readfds );
FD_SET( pServer->m_fd, &readfds );
timeout.tv_sec = 1;
@ -3097,11 +3174,15 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
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)
int accepting = 0;
if (s_accepting_workers)
accepting = __sync_add_and_fetch(s_accepting_workers, 0);
if (pServer->m_iCurChildren > 0 && accepting > 0)
{
usleep( 200 );
usleep(400);
while(accepting-- > 0)
sched_yield();
continue;
}
}
@ -3162,14 +3243,17 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
if (pthread_atfork_func)
(*pthread_atfork_func)(NULL, NULL, set_skip_write);
s_worker_status->m_connected = 1;
__sync_lock_test_and_set(&s_worker_status->m_state,
LSAPI_STATE_CONNECTED);
if (s_busy_workers)
__sync_add_and_fetch(s_busy_workers, 1);
lsapi_set_nblock( pReq->m_fd, 0 );
//keep it open if busy_count is used.
if (s_busy_workers && s_uid != 0)
if (s_busy_workers
&& *s_busy_workers > (pServer->m_iMaxChildren >> 1))
s_keepListener = 1;
else if ( pReq->m_fdListen != -1 )
if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
&& pReq->m_fdListen != -1 )
{
close( pReq->m_fdListen );
pReq->m_fdListen = -1;
@ -3295,6 +3379,9 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
timeout.tv_usec = 0;
if (fd == pReq->m_fdListen)
{
if (s_worker_status)
__sync_lock_test_and_set(&s_worker_status->m_state,
LSAPI_STATE_ACCEPTING);
if (s_accepting_workers)
__sync_fetch_and_add(s_accepting_workers, 1);
}
@ -3303,6 +3390,9 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
{
if (s_accepting_workers)
__sync_fetch_and_sub(s_accepting_workers, 1);
if (s_worker_status)
__sync_lock_test_and_set(&s_worker_status->m_state,
LSAPI_STATE_IDLE);
}
if ( ret == 0 )
@ -3310,7 +3400,8 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
if ( s_worker_status )
{
s_worker_status->m_inProcess = 0;
if (fd == pReq->m_fdListen)
if (fd == pReq->m_fdListen
&& (s_keepListener != 2 || !is_enough_free_mem()))
return -1;
}
++wait_secs;
@ -3337,7 +3428,8 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
if ( pReq->m_fd != -1 )
{
if (s_worker_status)
s_worker_status->m_connected = 1;
__sync_lock_test_and_set(&s_worker_status->m_state,
LSAPI_STATE_CONNECTED);
if (s_busy_workers)
__sync_fetch_and_add(s_busy_workers, 1);
@ -3345,7 +3437,7 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
lsapi_set_nblock( fd, 0 );
//init_conn_key( pReq->m_fd );
if ( !s_keepListener )
if (!s_keepListener)
{
close( pReq->m_fdListen );
pReq->m_fdListen = -1;
@ -3611,6 +3703,7 @@ static int lsapi_reopen_stderr(const char *p)
int LSAPI_Init_Env_Parameters( fn_select_t fp )
{
const char *p;
char ch;
int n;
int avoidFork = 0;
@ -3632,10 +3725,28 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
LSAPI_Set_Max_Reqs( n );
}
p = getenv( "LSAPI_KEEP_LISTEN" );
if ( p )
{
n = atoi( p );
s_keepListener = n;
}
p = getenv( "LSAPI_AVOID_FORK" );
if ( p )
{
avoidFork = atoi( p );
if (avoidFork)
{
s_keepListener = 2;
ch = *(p + strlen(p) - 1);
if ( ch == 'G' || ch == 'g' )
avoidFork *= 1024 * 1024 * 1024;
else if ( ch == 'M' || ch == 'm' )
avoidFork *= 1024 * 1024;
if (avoidFork >= 1024 * 10240)
s_min_avail_pages = avoidFork / 4096;
}
}
p = getenv( "LSAPI_ACCEPT_NOTIFY" );
@ -3670,14 +3781,6 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
LSAPI_Set_Max_Idle( n );
}
p = getenv( "LSAPI_KEEP_LISTEN" );
if ( p )
{
n = atoi( p );
s_keepListener = n;
}
if ( LSAPI_Is_Listen() )
{
n = 0;
@ -3688,7 +3791,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
n = atoi( p );
if ( n > 1 )
{
LSAPI_Init_Prefork_Server( n, fp, avoidFork );
LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
LSAPI_Set_Server_fd( g_req.m_fdListen );
}

View File

@ -265,6 +265,9 @@ static inline off_t LSAPI_GetReqBodyRemain_r( LSAPI_Request * pReq )
}
int LSAPI_End_Response_r(LSAPI_Request * pReq);
int LSAPI_Is_Listen(void);
@ -348,6 +351,9 @@ static inline int LSAPI_SetRespStatus( int code )
static inline int LSAPI_ErrResponse( int code, const char ** pRespHeaders, const char * pBody, int bodyLen )
{ return LSAPI_ErrResponse_r( &g_req, code, pRespHeaders, pBody, bodyLen ); }
static inline int LSAPI_End_Response(void)
{ return LSAPI_End_Response_r( &g_req ); }
int LSAPI_IsRunning(void);
int LSAPI_CreateListenSock( const char * pBind, int backlog );