summaryrefslogtreecommitdiff
path: root/sapi/litespeed
diff options
context:
space:
mode:
authorGeorge Wang <gwang@php.net>2019-07-04 12:03:21 -0400
committerGeorge Wang <gwang@php.net>2019-07-04 12:03:21 -0400
commit32af676bd9f13815d40138a2299e862a3c6985cf (patch)
treed2926549b745d8fadd4b55ce561f5d0e1b19f878 /sapi/litespeed
parent0e48e35e0485bc6d6458a45ecab5b19a0c2ec001 (diff)
downloadphp-git-32af676bd9f13815d40138a2299e862a3c6985cf.tar.gz
Updated to LiteSpeed SAPI V7.4.3
Increased response header count limit from 100 to 1000. Added crash handler to cleanly shutdown PHP request. Added CloudLinux mod_lsapi mode Fixed bug #76058
Diffstat (limited to 'sapi/litespeed')
-rw-r--r--sapi/litespeed/lsapi_main.c270
-rw-r--r--sapi/litespeed/lsapilib.h2
2 files changed, 268 insertions, 4 deletions
diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c
index 9087ae9f3c..a0d464c2a5 100644
--- a/sapi/litespeed/lsapi_main.c
+++ b/sapi/litespeed/lsapi_main.c
@@ -311,7 +311,8 @@ static void sapi_lsapi_register_variables(zval *track_vars_array)
static size_t sapi_lsapi_read_post(char *buffer, size_t count_bytes)
{
if ( lsapi_mode ) {
- return LSAPI_ReadReqBody( buffer, (unsigned long long)count_bytes );
+ ssize_t rv = LSAPI_ReadReqBody(buffer, (unsigned long long)count_bytes);
+ return (rv >= 0) ? (size_t)rv : 0;
} else {
return 0;
}
@@ -334,12 +335,165 @@ static char *sapi_lsapi_read_cookies(void)
/* }}} */
+typedef struct _http_error {
+ int code;
+ const char* msg;
+} http_error;
+
+static const http_error http_error_codes[] = {
+ {100, "Continue"},
+ {101, "Switching Protocols"},
+ {200, "OK"},
+ {201, "Created"},
+ {202, "Accepted"},
+ {203, "Non-Authoritative Information"},
+ {204, "No Content"},
+ {205, "Reset Content"},
+ {206, "Partial Content"},
+ {300, "Multiple Choices"},
+ {301, "Moved Permanently"},
+ {302, "Moved Temporarily"},
+ {303, "See Other"},
+ {304, "Not Modified"},
+ {305, "Use Proxy"},
+ {400, "Bad Request"},
+ {401, "Unauthorized"},
+ {402, "Payment Required"},
+ {403, "Forbidden"},
+ {404, "Not Found"},
+ {405, "Method Not Allowed"},
+ {406, "Not Acceptable"},
+ {407, "Proxy Authentication Required"},
+ {408, "Request Time-out"},
+ {409, "Conflict"},
+ {410, "Gone"},
+ {411, "Length Required"},
+ {412, "Precondition Failed"},
+ {413, "Request Entity Too Large"},
+ {414, "Request-URI Too Large"},
+ {415, "Unsupported Media Type"},
+ {428, "Precondition Required"},
+ {429, "Too Many Requests"},
+ {431, "Request Header Fields Too Large"},
+ {451, "Unavailable For Legal Reasons"},
+ {500, "Internal Server Error"},
+ {501, "Not Implemented"},
+ {502, "Bad Gateway"},
+ {503, "Service Unavailable"},
+ {504, "Gateway Time-out"},
+ {505, "HTTP Version not supported"},
+ {511, "Network Authentication Required"},
+ {0, NULL}
+};
+
+
+static int sapi_lsapi_send_headers_like_cgi(sapi_headers_struct *sapi_headers)
+{
+ char buf[SAPI_LSAPI_MAX_HEADER_LENGTH];
+ sapi_header_struct *h;
+ zend_llist_position pos;
+ zend_bool ignore_status = 0;
+ int response_status = SG(sapi_headers).http_response_code;
+
+ if (SG(request_info).no_headers == 1) {
+ LSAPI_FinalizeRespHeaders();
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
+ }
+
+ if (SG(sapi_headers).http_response_code != 200)
+ {
+ int len;
+ zend_bool has_status = 0;
+
+ char *s;
+
+ if (SG(sapi_headers).http_status_line &&
+ (s = strchr(SG(sapi_headers).http_status_line, ' ')) != 0 &&
+ (s - SG(sapi_headers).http_status_line) >= 5 &&
+ strncasecmp(SG(sapi_headers).http_status_line, "HTTP/", 5) == 0
+ ) {
+ len = slprintf(buf, sizeof(buf), "Status:%s", s);
+ response_status = atoi((s + 1));
+ } else {
+ h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
+ while (h) {
+ if (h->header_len > sizeof("Status:")-1 &&
+ strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
+ ) {
+ has_status = 1;
+ break;
+ }
+ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ }
+ if (!has_status) {
+ http_error *err = (http_error*)http_error_codes;
+
+ while (err->code != 0) {
+ if (err->code == SG(sapi_headers).http_response_code) {
+ break;
+ }
+ err++;
+ }
+ if (err->msg) {
+ len = slprintf(buf, sizeof(buf), "Status: %d %s", SG(sapi_headers).http_response_code, err->msg);
+ } else {
+ len = slprintf(buf, sizeof(buf), "Status: %d", SG(sapi_headers).http_response_code);
+ }
+ }
+ }
+
+ if (!has_status) {
+ LSAPI_AppendRespHeader( buf, len );
+ ignore_status = 1;
+ }
+ }
+
+ h = (sapi_header_struct*)zend_llist_get_first_ex(&sapi_headers->headers, &pos);
+ while (h) {
+ /* prevent CRLFCRLF */
+ if (h->header_len) {
+ if (h->header_len > sizeof("Status:")-1 &&
+ strncasecmp(h->header, "Status:", sizeof("Status:")-1) == 0
+ ) {
+ if (!ignore_status) {
+ ignore_status = 1;
+ LSAPI_AppendRespHeader(h->header, h->header_len);
+ }
+ } else if (response_status == 304 && h->header_len > sizeof("Content-Type:")-1 &&
+ strncasecmp(h->header, "Content-Type:", sizeof("Content-Type:")-1) == 0
+ ) {
+ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ continue;
+ } else {
+ LSAPI_AppendRespHeader(h->header, h->header_len);
+ }
+ }
+ h = (sapi_header_struct*)zend_llist_get_next_ex(&sapi_headers->headers, &pos);
+ }
+
+ LSAPI_FinalizeRespHeaders();
+ return SAPI_HEADER_SENT_SUCCESSFULLY;
+}
+
+/*
+ mod_lsapi mode or legacy LS mode
+*/
+static int mod_lsapi_mode = 0;
+
+
/* {{{ sapi_lsapi_send_headers
*/
static int sapi_lsapi_send_headers(sapi_headers_struct *sapi_headers)
{
sapi_header_struct *h;
zend_llist_position pos;
+
+ if ( mod_lsapi_mode ) {
+ /* mod_lsapi mode */
+ return sapi_lsapi_send_headers_like_cgi(sapi_headers);
+ }
+
+ /* Legacy mode */
if ( lsapi_mode ) {
LSAPI_SetRespStatus( SG(sapi_headers).http_response_code );
@@ -466,7 +620,7 @@ static int sapi_lsapi_activate()
static sapi_module_struct lsapi_sapi_module =
{
"litespeed",
- "LiteSpeed V7.3.2",
+ "LiteSpeed V7.4.3",
php_lsapi_startup, /* startup */
php_module_shutdown_wrapper, /* shutdown */
@@ -541,6 +695,66 @@ static int lsapi_execute_script( zend_file_handle * file_handle)
}
+static void lsapi_sigsegv( int signal )
+{
+ //fprintf(stderr, "lsapi_sigsegv: %d: Segmentation violation signal is caught during request shutdown\n", getpid());
+ _exit(1);
+}
+
+static int clean_onexit = 1;
+
+static void lsapi_sigterm( int signal )
+{
+ struct sigaction act, old_act;
+ int sa_rc;
+
+ // fprintf(stderr, "lsapi_sigterm: %d: clean_onexit %d\n", getpid(), clean_onexit );
+ if(!clean_onexit)
+ {
+ clean_onexit = 1;
+ act.sa_flags = 0;
+ act.sa_handler = lsapi_sigsegv;
+ sa_rc = sigaction( SIGINT, &act, &old_act );
+ sa_rc = sigaction( SIGQUIT, &act, &old_act );
+ sa_rc = sigaction( SIGILL, &act, &old_act );
+ sa_rc = sigaction( SIGABRT, &act, &old_act );
+ sa_rc = sigaction( SIGBUS, &act, &old_act );
+ sa_rc = sigaction( SIGSEGV, &act, &old_act );
+ sa_rc = sigaction( SIGTERM, &act, &old_act );
+
+ zend_try {
+ php_request_shutdown(NULL);
+ } zend_end_try();
+ }
+ exit(1);
+}
+
+static void lsapi_atexit( void )
+{
+ struct sigaction act, old_act;
+ int sa_rc;
+
+ //fprintf(stderr, "lsapi_atexit: %d: clean_onexit %d\n", getpid(), clean_onexit );
+ if(!clean_onexit)
+ {
+ clean_onexit = 1;
+ act.sa_flags = 0;
+ act.sa_handler = lsapi_sigsegv;
+ sa_rc = sigaction( SIGINT, &act, &old_act );
+ sa_rc = sigaction( SIGQUIT, &act, &old_act );
+ sa_rc = sigaction( SIGILL, &act, &old_act );
+ sa_rc = sigaction( SIGABRT, &act, &old_act );
+ sa_rc = sigaction( SIGBUS, &act, &old_act );
+ sa_rc = sigaction( SIGSEGV, &act, &old_act );
+ sa_rc = sigaction( SIGTERM, &act, &old_act );
+
+ //fprintf(stderr, "lsapi_atexit: %d: before php_request_shutdown\n", getpid(), clean_onexit );
+ zend_try {
+ php_request_shutdown(NULL);
+ } zend_end_try();
+ }
+}
+
static int lsapi_module_main(int show_source)
{
zend_file_handle file_handle;
@@ -549,6 +763,8 @@ static int lsapi_module_main(int show_source)
return -1;
}
+ clean_onexit = 0;
+
if (show_source) {
zend_syntax_highlighter_ini syntax_highlighter_ini;
@@ -559,6 +775,9 @@ static int lsapi_module_main(int show_source)
}
zend_try {
php_request_shutdown(NULL);
+
+ clean_onexit = 1;
+
memset( argv0, 0, 46 );
} zend_end_try();
return 0;
@@ -576,7 +795,16 @@ static int alter_ini( const char * pKey, int keyLen, const char * pValue, int va
++pKey;
if ( *pKey == 4 ) {
type = ZEND_INI_SYSTEM;
- stage = PHP_INI_STAGE_ACTIVATE;
+ /*
+ Use ACTIVATE stage in legacy mode only.
+
+ RUNTIME stage should be used here,
+ as with ACTIVATE it's impossible to change the option from script with ini_set
+ */
+ if(!mod_lsapi_mode)
+ {
+ stage = PHP_INI_STAGE_ACTIVATE;
+ }
}
else
{
@@ -1245,6 +1473,16 @@ int main( int argc, char * argv[] )
int slow_script_msec = 0;
char time_buf[40];
+ struct sigaction act, old_act;
+ struct sigaction INT_act;
+ struct sigaction QUIT_act;
+ struct sigaction ILL_act;
+ struct sigaction ABRT_act;
+ struct sigaction BUS_act;
+ struct sigaction SEGV_act;
+ struct sigaction TERM_act;
+ int sa_rc;
+
#ifdef HAVE_SIGNAL_H
#if defined(SIGPIPE) && defined(SIG_IGN)
signal(SIGPIPE, SIG_IGN);
@@ -1346,6 +1584,17 @@ int main( int argc, char * argv[] )
int iRequestsProcessed = 0;
int result;
+ act.sa_flags = SA_NODEFER;
+ act.sa_handler = lsapi_sigterm;
+ sa_rc = sigaction( SIGINT, &act, &INT_act );
+ sa_rc = sigaction( SIGQUIT, &act, &QUIT_act );
+ sa_rc = sigaction( SIGILL, &act, &ILL_act );
+ sa_rc = sigaction( SIGABRT, &act, &ABRT_act );
+ sa_rc = sigaction( SIGBUS, &act, &BUS_act );
+ sa_rc = sigaction( SIGSEGV, &act, &SEGV_act );
+ sa_rc = sigaction( SIGTERM, &act, &TERM_act );
+ atexit(lsapi_atexit);
+
while( ( result = LSAPI_Prefork_Accept_r( &g_req )) >= 0 ) {
#if defined(linux) || defined(__linux) || defined(__linux__) || defined(__gnu_linux__)
if (is_criu && !result) {
@@ -1375,6 +1624,15 @@ int main( int argc, char * argv[] )
break;
}
}
+
+ sa_rc = sigaction( SIGINT, &INT_act, &old_act );
+ sa_rc = sigaction( SIGQUIT, &QUIT_act, &old_act );
+ sa_rc = sigaction( SIGILL, &ILL_act, &old_act );
+ sa_rc = sigaction( SIGABRT, &ABRT_act, &old_act );
+ sa_rc = sigaction( SIGBUS, &BUS_act, &old_act );
+ sa_rc = sigaction( SIGSEGV, &SEGV_act, &old_act );
+ sa_rc = sigaction( SIGTERM, &TERM_act, &old_act );
+
php_module_shutdown();
#ifdef ZTS
@@ -1417,6 +1675,12 @@ static PHP_MINIT_FUNCTION(litespeed)
if (p && 0 == strcasecmp(p, "on"))
parse_user_ini = 1;
+ /*
+ * mod_lsapi always sets this env var,
+ * so we can detect mod_lsapi mode with its presense.
+ */
+ mod_lsapi_mode = ( getenv("LSAPI_DISABLE_CPAN_BEHAV") != NULL );
+
/* REGISTER_INI_ENTRIES(); */
return SUCCESS;
}
diff --git a/sapi/litespeed/lsapilib.h b/sapi/litespeed/lsapilib.h
index f6e1f93067..9e1a9e1494 100644
--- a/sapi/litespeed/lsapilib.h
+++ b/sapi/litespeed/lsapilib.h
@@ -71,7 +71,7 @@ struct LSAPI_key_value_pair
};
-#define LSAPI_MAX_RESP_HEADERS 100
+#define LSAPI_MAX_RESP_HEADERS 1000
typedef struct lsapi_request
{