Skip to content

Commit 1e7f1b9

Browse files
author
George Wang
committed
LiteSpeed SAPI 7.3, better process management, new API function litespeed_finish_request().
1 parent d07a6fd commit 1e7f1b9

File tree

3 files changed

+152
-26
lines changed

3 files changed

+152
-26
lines changed

sapi/litespeed/lsapi_main.c

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -466,7 +466,7 @@ static int sapi_lsapi_activate()
466466
static sapi_module_struct lsapi_sapi_module =
467467
{
468468
"litespeed",
469-
"LiteSpeed V7.2",
469+
"LiteSpeed V7.3",
470470

471471
php_lsapi_startup, /* startup */
472472
php_module_shutdown_wrapper, /* shutdown */
@@ -1394,16 +1394,19 @@ ZEND_END_ARG_INFO()
13941394
PHP_FUNCTION(litespeed_request_headers);
13951395
PHP_FUNCTION(litespeed_response_headers);
13961396
PHP_FUNCTION(apache_get_modules);
1397+
PHP_FUNCTION(litespeed_finish_request);
13971398

13981399
PHP_MINFO_FUNCTION(litespeed);
13991400

14001401
zend_function_entry litespeed_functions[] = {
14011402
PHP_FE(litespeed_request_headers, arginfo_litespeed__void)
14021403
PHP_FE(litespeed_response_headers, arginfo_litespeed__void)
14031404
PHP_FE(apache_get_modules, arginfo_litespeed__void)
1405+
PHP_FE(litespeed_finish_request, arginfo_litespeed__void)
14041406
PHP_FALIAS(getallheaders, litespeed_request_headers, arginfo_litespeed__void)
14051407
PHP_FALIAS(apache_request_headers, litespeed_request_headers, arginfo_litespeed__void)
14061408
PHP_FALIAS(apache_response_headers, litespeed_response_headers, arginfo_litespeed__void)
1409+
PHP_FALIAS(fastcgi_finish_request, litespeed_finish_request, arginfo_litespeed__void)
14071410
{NULL, NULL, NULL}
14081411
};
14091412

@@ -1532,6 +1535,20 @@ PHP_FUNCTION(apache_get_modules)
15321535
/* }}} */
15331536

15341537

1538+
/* {{{ proto array litespeed_finish_request(void)
1539+
Flushes all response data to the client */
1540+
PHP_FUNCTION(litespeed_finish_request)
1541+
{
1542+
if (ZEND_NUM_ARGS() > 0) {
1543+
WRONG_PARAM_COUNT;
1544+
}
1545+
if (LSAPI_End_Response() != -1) {
1546+
RETURN_TRUE;
1547+
}
1548+
RETURN_FALSE;
1549+
}
1550+
/* }}} */
1551+
15351552
/*
15361553
* Local variables:
15371554
* tab-width: 4

sapi/litespeed/lsapilib.c

Lines changed: 128 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
5555
#include <fcntl.h>
5656
#include <limits.h>
5757
#include <sys/stat.h>
58+
#include <sched.h>
5859
#include <signal.h>
5960
#include <stdlib.h>
6061
#include <stdio.h>
@@ -113,18 +114,26 @@ typedef struct lsapi_MD5Context lsapi_MD5_CTX;
113114
#define LSAPI_ST_REQ_BODY 2
114115
#define LSAPI_ST_RESP_HEADER 4
115116
#define LSAPI_ST_RESP_BODY 8
117+
#define LSAPI_ST_BACKGROUND 16
116118

117119
#define LSAPI_RESP_BUF_SIZE 8192
118120
#define LSAPI_INIT_RESP_HEADER_LEN 4096
119121

122+
enum
123+
{
124+
LSAPI_STATE_IDLE,
125+
LSAPI_STATE_CONNECTED,
126+
LSAPI_STATE_ACCEPTING,
127+
};
128+
120129
typedef struct _lsapi_child_status
121130
{
122131
int m_pid;
123132
long m_tmStart;
124133

125134
volatile short m_iKillSent;
126135
volatile char m_inProcess;
127-
volatile char m_connected;
136+
volatile char m_state;
128137
volatile int m_iReqCounter;
129138

130139
volatile long m_tmWaitBegin;
@@ -156,6 +165,9 @@ static int s_max_busy_workers = -1;
156165
static char *s_stderr_log_path = NULL;
157166
static int s_stderr_is_pipe = 0;
158167
static int s_ignore_pid = -1;
168+
static size_t s_total_pages = 1;
169+
static size_t s_min_avail_pages = 256 * 1024;
170+
static size_t *s_avail_pages = &s_total_pages;
159171

160172
LSAPI_Request g_req =
161173
{ .m_fdListen = -1, .m_fd = -1 };
@@ -415,7 +427,7 @@ static void lsapi_close_connection(LSAPI_Request *pReq)
415427
if (s_busy_workers)
416428
__sync_fetch_and_sub(s_busy_workers, 1);
417429
if (s_worker_status)
418-
s_worker_status->m_connected = 0;
430+
__sync_lock_test_and_set(&s_worker_status->m_state, LSAPI_STATE_IDLE);
419431
}
420432

421433

@@ -1558,7 +1570,8 @@ int LSAPI_Accept_r( LSAPI_Request * pReq )
15581570
else
15591571
{
15601572
if (s_worker_status)
1561-
s_worker_status->m_connected = 1;
1573+
__sync_lock_test_and_set(&s_worker_status->m_state,
1574+
LSAPI_STATE_CONNECTED);
15621575
if (s_busy_workers)
15631576
__sync_fetch_and_add(s_busy_workers, 1);
15641577
lsapi_set_nblock( pReq->m_fd , 0 );
@@ -1621,6 +1634,37 @@ int LSAPI_Finish_r( LSAPI_Request * pReq )
16211634
}
16221635

16231636

1637+
int LSAPI_End_Response_r(LSAPI_Request * pReq)
1638+
{
1639+
if (!pReq)
1640+
return -1;
1641+
if (pReq->m_reqState)
1642+
{
1643+
if ( pReq->m_fd != -1 )
1644+
{
1645+
if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
1646+
{
1647+
LSAPI_FinalizeRespHeaders_r( pReq );
1648+
}
1649+
if ( pReq->m_pRespBufPos != pReq->m_pRespBuf )
1650+
{
1651+
Flush_RespBuf_r( pReq );
1652+
}
1653+
1654+
pReq->m_pIovecCur->iov_base = (void *)&finish;
1655+
pReq->m_pIovecCur->iov_len = LSAPI_PACKET_HEADER_LEN;
1656+
pReq->m_totalLen += LSAPI_PACKET_HEADER_LEN;
1657+
++pReq->m_pIovecCur;
1658+
LSAPI_Flush_r( pReq );
1659+
}
1660+
send_conn_close_notification(pReq->m_fd);
1661+
lsapi_close_connection(pReq);
1662+
pReq->m_reqState |= LSAPI_ST_BACKGROUND;
1663+
}
1664+
return 0;
1665+
}
1666+
1667+
16241668
void LSAPI_Reset_r( LSAPI_Request * pReq )
16251669
{
16261670
pReq->m_pRespBufPos = pReq->m_pRespBuf;
@@ -1806,7 +1850,11 @@ ssize_t LSAPI_Write_r( LSAPI_Request * pReq, const char * pBuf, size_t len )
18061850
ssize_t packetLen;
18071851
int skip = 0;
18081852

1809-
if ( !pReq || !pBuf || (pReq->m_fd == -1) )
1853+
if (!pReq || !pBuf)
1854+
return -1;
1855+
if (pReq->m_reqState & LSAPI_ST_BACKGROUND)
1856+
return len;
1857+
if (pReq->m_fd == -1)
18101858
return -1;
18111859
if ( pReq->m_reqState & LSAPI_ST_RESP_HEADER )
18121860
{
@@ -2708,6 +2756,9 @@ int LSAPI_Init_Prefork_Server( int max_children, fn_select_t fp, int avoidFork )
27082756
s_ppid = getppid();
27092757
s_pid = getpid();
27102758
setpgid( s_pid, s_pid );
2759+
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
2760+
s_total_pages = sysconf(_SC_PHYS_PAGES);
2761+
#endif
27112762
g_prefork_server->m_iAvoidFork = avoidFork;
27122763
g_prefork_server->m_iMaxChildren = max_children;
27132764

@@ -2842,11 +2893,19 @@ static void lsapi_sigchild( int signal )
28422893
child_status = find_child_status( pid );
28432894
if ( child_status )
28442895
{
2845-
if (child_status->m_connected)
2896+
if (__sync_bool_compare_and_swap(&child_status->m_state,
2897+
LSAPI_STATE_CONNECTED,
2898+
LSAPI_STATE_IDLE))
28462899
{
28472900
if (s_busy_workers)
28482901
__sync_fetch_and_sub(s_busy_workers, 1);
2849-
child_status->m_connected = 0;
2902+
}
2903+
else if (__sync_bool_compare_and_swap(&child_status->m_state,
2904+
LSAPI_STATE_ACCEPTING,
2905+
LSAPI_STATE_IDLE))
2906+
{
2907+
if (s_accepting_workers)
2908+
__sync_fetch_and_sub(s_accepting_workers, 1);
28502909
}
28512910
child_status->m_pid = 0;
28522911
--g_prefork_server->m_iCurChildren;
@@ -2882,6 +2941,7 @@ static int lsapi_init_children_status(void)
28822941
s_busy_workers = (int *)g_prefork_server->m_pChildrenStatusEnd;
28832942
s_accepting_workers = s_busy_workers + 1;
28842943
s_global_counter = s_accepting_workers + 1;
2944+
s_avail_pages = (size_t *)(s_global_counter + 1);
28852945
return 0;
28862946
}
28872947

@@ -3021,6 +3081,17 @@ void set_skip_write()
30213081
{ s_skip_write = 1; }
30223082

30233083

3084+
int is_enough_free_mem()
3085+
{
3086+
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3087+
//minimum 1GB or 10% available free memory
3088+
return (*s_avail_pages > s_min_avail_pages
3089+
|| (*s_avail_pages * 10) / s_total_pages > 0);
3090+
#endif
3091+
return 1;
3092+
}
3093+
3094+
30243095
static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
30253096
LSAPI_Request * pReq )
30263097
{
@@ -3090,18 +3161,28 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
30903161
}
30913162
}
30923163

3164+
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
3165+
*s_avail_pages = sysconf(_SC_AVPHYS_PAGES);
3166+
lsapi_log("Memory total: %zd, free: %zd, free %%%zd\n",
3167+
s_total_pages, *s_avail_pages, *s_avail_pages * 100 / s_total_pages);
3168+
3169+
#endif
30933170
FD_ZERO( &readfds );
30943171
FD_SET( pServer->m_fd, &readfds );
30953172
timeout.tv_sec = 1;
30963173
timeout.tv_usec = 0;
30973174
ret = (*g_fnSelect)(pServer->m_fd+1, &readfds, NULL, NULL, &timeout);
30983175
if (ret == 1 )
30993176
{
3100-
if (pServer->m_iCurChildren >= pServer->m_iMaxChildren
3101-
&& s_accepting_workers
3102-
&& (ret = __sync_add_and_fetch(s_accepting_workers, 0)) > 0)
3177+
int accepting = 0;
3178+
if (s_accepting_workers)
3179+
accepting = __sync_add_and_fetch(s_accepting_workers, 0);
3180+
3181+
if (pServer->m_iCurChildren > 0 && accepting > 0)
31033182
{
3104-
usleep( 200 );
3183+
usleep(400);
3184+
while(accepting-- > 0)
3185+
sched_yield();
31053186
continue;
31063187
}
31073188
}
@@ -3162,14 +3243,17 @@ static int lsapi_prefork_server_accept( lsapi_prefork_server * pServer,
31623243
if (pthread_atfork_func)
31633244
(*pthread_atfork_func)(NULL, NULL, set_skip_write);
31643245

3165-
s_worker_status->m_connected = 1;
3246+
__sync_lock_test_and_set(&s_worker_status->m_state,
3247+
LSAPI_STATE_CONNECTED);
31663248
if (s_busy_workers)
31673249
__sync_add_and_fetch(s_busy_workers, 1);
31683250
lsapi_set_nblock( pReq->m_fd, 0 );
31693251
//keep it open if busy_count is used.
3170-
if (s_busy_workers && s_uid != 0)
3252+
if (s_busy_workers
3253+
&& *s_busy_workers > (pServer->m_iMaxChildren >> 1))
31713254
s_keepListener = 1;
3172-
else if ( pReq->m_fdListen != -1 )
3255+
if ((s_uid == 0 || !s_keepListener || !is_enough_free_mem())
3256+
&& pReq->m_fdListen != -1 )
31733257
{
31743258
close( pReq->m_fdListen );
31753259
pReq->m_fdListen = -1;
@@ -3295,6 +3379,9 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
32953379
timeout.tv_usec = 0;
32963380
if (fd == pReq->m_fdListen)
32973381
{
3382+
if (s_worker_status)
3383+
__sync_lock_test_and_set(&s_worker_status->m_state,
3384+
LSAPI_STATE_ACCEPTING);
32983385
if (s_accepting_workers)
32993386
__sync_fetch_and_add(s_accepting_workers, 1);
33003387
}
@@ -3303,14 +3390,18 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
33033390
{
33043391
if (s_accepting_workers)
33053392
__sync_fetch_and_sub(s_accepting_workers, 1);
3393+
if (s_worker_status)
3394+
__sync_lock_test_and_set(&s_worker_status->m_state,
3395+
LSAPI_STATE_IDLE);
33063396
}
33073397

33083398
if ( ret == 0 )
33093399
{
33103400
if ( s_worker_status )
33113401
{
33123402
s_worker_status->m_inProcess = 0;
3313-
if (fd == pReq->m_fdListen)
3403+
if (fd == pReq->m_fdListen
3404+
&& (s_keepListener != 2 || !is_enough_free_mem()))
33143405
return -1;
33153406
}
33163407
++wait_secs;
@@ -3337,15 +3428,16 @@ int LSAPI_Prefork_Accept_r( LSAPI_Request * pReq )
33373428
if ( pReq->m_fd != -1 )
33383429
{
33393430
if (s_worker_status)
3340-
s_worker_status->m_connected = 1;
3431+
__sync_lock_test_and_set(&s_worker_status->m_state,
3432+
LSAPI_STATE_CONNECTED);
33413433
if (s_busy_workers)
33423434
__sync_fetch_and_add(s_busy_workers, 1);
33433435

33443436
fd = pReq->m_fd;
33453437

33463438
lsapi_set_nblock( fd, 0 );
33473439
//init_conn_key( pReq->m_fd );
3348-
if ( !s_keepListener )
3440+
if (!s_keepListener)
33493441
{
33503442
close( pReq->m_fdListen );
33513443
pReq->m_fdListen = -1;
@@ -3611,6 +3703,7 @@ static int lsapi_reopen_stderr(const char *p)
36113703
int LSAPI_Init_Env_Parameters( fn_select_t fp )
36123704
{
36133705
const char *p;
3706+
char ch;
36143707
int n;
36153708
int avoidFork = 0;
36163709

@@ -3632,10 +3725,28 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
36323725
LSAPI_Set_Max_Reqs( n );
36333726
}
36343727

3728+
p = getenv( "LSAPI_KEEP_LISTEN" );
3729+
if ( p )
3730+
{
3731+
n = atoi( p );
3732+
s_keepListener = n;
3733+
}
3734+
36353735
p = getenv( "LSAPI_AVOID_FORK" );
36363736
if ( p )
36373737
{
36383738
avoidFork = atoi( p );
3739+
if (avoidFork)
3740+
{
3741+
s_keepListener = 2;
3742+
ch = *(p + strlen(p) - 1);
3743+
if ( ch == 'G' || ch == 'g' )
3744+
avoidFork *= 1024 * 1024 * 1024;
3745+
else if ( ch == 'M' || ch == 'm' )
3746+
avoidFork *= 1024 * 1024;
3747+
if (avoidFork >= 1024 * 10240)
3748+
s_min_avail_pages = avoidFork / 4096;
3749+
}
36393750
}
36403751

36413752
p = getenv( "LSAPI_ACCEPT_NOTIFY" );
@@ -3670,14 +3781,6 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
36703781
LSAPI_Set_Max_Idle( n );
36713782
}
36723783

3673-
p = getenv( "LSAPI_KEEP_LISTEN" );
3674-
if ( p )
3675-
{
3676-
n = atoi( p );
3677-
s_keepListener = n;
3678-
}
3679-
3680-
36813784
if ( LSAPI_Is_Listen() )
36823785
{
36833786
n = 0;
@@ -3688,7 +3791,7 @@ int LSAPI_Init_Env_Parameters( fn_select_t fp )
36883791
n = atoi( p );
36893792
if ( n > 1 )
36903793
{
3691-
LSAPI_Init_Prefork_Server( n, fp, avoidFork );
3794+
LSAPI_Init_Prefork_Server( n, fp, avoidFork != 0 );
36923795
LSAPI_Set_Server_fd( g_req.m_fdListen );
36933796
}
36943797

0 commit comments

Comments
 (0)