mirror of
https://github.com/php/php-src.git
synced 2026-04-11 10:03:18 +02:00
Refactor accel_finish_startup
This commit is contained in:
@@ -4572,206 +4572,227 @@ static void preload_send_header(sapi_header_struct *sapi_header, void *server_co
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef ZEND_WIN32
|
||||
static int accel_finish_startup_preload(bool in_child)
|
||||
{
|
||||
int ret = SUCCESS;
|
||||
int rc;
|
||||
int orig_error_reporting;
|
||||
|
||||
int (*orig_activate)(void) = sapi_module.activate;
|
||||
int (*orig_deactivate)(void) = sapi_module.deactivate;
|
||||
void (*orig_register_server_variables)(zval *track_vars_array) = sapi_module.register_server_variables;
|
||||
int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers) = sapi_module.header_handler;
|
||||
int (*orig_send_headers)(sapi_headers_struct *sapi_headers) = sapi_module.send_headers;
|
||||
void (*orig_send_header)(sapi_header_struct *sapi_header, void *server_context)= sapi_module.send_header;
|
||||
char *(*orig_getenv)(const char *name, size_t name_len) = sapi_module.getenv;
|
||||
size_t (*orig_ub_write)(const char *str, size_t str_length) = sapi_module.ub_write;
|
||||
void (*orig_flush)(void *server_context) = sapi_module.flush;
|
||||
#ifdef ZEND_SIGNALS
|
||||
bool old_reset_signals = SIGG(reset);
|
||||
#endif
|
||||
|
||||
sapi_module.activate = NULL;
|
||||
sapi_module.deactivate = NULL;
|
||||
sapi_module.register_server_variables = NULL;
|
||||
sapi_module.header_handler = preload_header_handler;
|
||||
sapi_module.send_headers = preload_send_headers;
|
||||
sapi_module.send_header = preload_send_header;
|
||||
sapi_module.getenv = NULL;
|
||||
sapi_module.ub_write = preload_ub_write;
|
||||
sapi_module.flush = preload_flush;
|
||||
|
||||
zend_interned_strings_switch_storage(1);
|
||||
|
||||
#ifdef ZEND_SIGNALS
|
||||
SIGG(reset) = false;
|
||||
#endif
|
||||
|
||||
orig_error_reporting = EG(error_reporting);
|
||||
EG(error_reporting) = 0;
|
||||
|
||||
rc = php_request_startup();
|
||||
|
||||
EG(error_reporting) = orig_error_reporting;
|
||||
|
||||
if (rc == SUCCESS) {
|
||||
bool orig_report_memleaks;
|
||||
|
||||
/* don't send headers */
|
||||
SG(headers_sent) = true;
|
||||
SG(request_info).no_headers = true;
|
||||
php_output_set_status(0);
|
||||
|
||||
ZCG(auto_globals_mask) = 0;
|
||||
ZCG(request_time) = (time_t)sapi_get_request_time();
|
||||
ZCG(cache_opline) = NULL;
|
||||
ZCG(cache_persistent_script) = NULL;
|
||||
ZCG(include_path_key_len) = 0;
|
||||
ZCG(include_path_check) = true;
|
||||
|
||||
ZCG(cwd) = NULL;
|
||||
ZCG(cwd_key_len) = 0;
|
||||
ZCG(cwd_check) = true;
|
||||
|
||||
if (accel_preload(ZCG(accel_directives).preload, in_child) != SUCCESS) {
|
||||
ret = FAILURE;
|
||||
}
|
||||
preload_flush(NULL);
|
||||
|
||||
orig_report_memleaks = PG(report_memleaks);
|
||||
PG(report_memleaks) = false;
|
||||
#ifdef ZEND_SIGNALS
|
||||
/* We may not have registered signal handlers due to SIGG(reset)=0, so
|
||||
* also disable the check that they are registered. */
|
||||
SIGG(check) = false;
|
||||
#endif
|
||||
php_request_shutdown(NULL); /* calls zend_shared_alloc_unlock(); */
|
||||
PG(report_memleaks) = orig_report_memleaks;
|
||||
} else {
|
||||
zend_shared_alloc_unlock();
|
||||
ret = FAILURE;
|
||||
}
|
||||
#ifdef ZEND_SIGNALS
|
||||
SIGG(reset) = old_reset_signals;
|
||||
#endif
|
||||
|
||||
sapi_module.activate = orig_activate;
|
||||
sapi_module.deactivate = orig_deactivate;
|
||||
sapi_module.register_server_variables = orig_register_server_variables;
|
||||
sapi_module.header_handler = orig_header_handler;
|
||||
sapi_module.send_headers = orig_send_headers;
|
||||
sapi_module.send_header = orig_send_header;
|
||||
sapi_module.getenv = orig_getenv;
|
||||
sapi_module.ub_write = orig_ub_write;
|
||||
sapi_module.flush = orig_flush;
|
||||
|
||||
sapi_activate();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int accel_finish_startup_preload_subprocess(pid_t *pid)
|
||||
{
|
||||
uid_t euid = geteuid();
|
||||
if (euid != 0) {
|
||||
if (ZCG(accel_directives).preload_user
|
||||
&& *ZCG(accel_directives).preload_user) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
|
||||
}
|
||||
|
||||
*pid = -1;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (!ZCG(accel_directives).preload_user
|
||||
|| !*ZCG(accel_directives).preload_user) {
|
||||
|
||||
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
struct passwd *pw = getpwnam(ZCG(accel_directives).preload_user);
|
||||
if (pw == NULL) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (pw->pw_uid == euid) {
|
||||
*pid = -1;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
*pid = fork();
|
||||
if (*pid == -1) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to fork()");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (*pid == 0) { /* children */
|
||||
if (setgid(pw->pw_gid) < 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
|
||||
exit(1);
|
||||
}
|
||||
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(pw->pw_uid) < 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
#endif /* ZEND_WIN32 */
|
||||
|
||||
static int accel_finish_startup(void)
|
||||
{
|
||||
if (!ZCG(enabled) || !accel_startup_ok) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
|
||||
#ifdef ZEND_WIN32
|
||||
zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Preloading is not supported on Windows");
|
||||
return FAILURE;
|
||||
#else
|
||||
bool in_child = false;
|
||||
int ret = SUCCESS;
|
||||
int rc;
|
||||
int orig_error_reporting;
|
||||
|
||||
int (*orig_activate)(void) = sapi_module.activate;
|
||||
int (*orig_deactivate)(void) = sapi_module.deactivate;
|
||||
void (*orig_register_server_variables)(zval *track_vars_array) = sapi_module.register_server_variables;
|
||||
int (*orig_header_handler)(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers) = sapi_module.header_handler;
|
||||
int (*orig_send_headers)(sapi_headers_struct *sapi_headers) = sapi_module.send_headers;
|
||||
void (*orig_send_header)(sapi_header_struct *sapi_header, void *server_context)= sapi_module.send_header;
|
||||
char *(*orig_getenv)(const char *name, size_t name_len) = sapi_module.getenv;
|
||||
size_t (*orig_ub_write)(const char *str, size_t str_length) = sapi_module.ub_write;
|
||||
void (*orig_flush)(void *server_context) = sapi_module.flush;
|
||||
#ifdef ZEND_SIGNALS
|
||||
bool old_reset_signals = SIGG(reset);
|
||||
#endif
|
||||
|
||||
if (UNEXPECTED(file_cache_only)) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading doesn't work in \"file_cache_only\" mode");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* exclusive lock */
|
||||
zend_shared_alloc_lock();
|
||||
|
||||
if (ZCSG(preload_script)) {
|
||||
/* Preloading was done in another process */
|
||||
preload_load();
|
||||
zend_shared_alloc_unlock();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
uid_t euid = geteuid();
|
||||
if (euid == 0) {
|
||||
pid_t pid;
|
||||
struct passwd *pw;
|
||||
|
||||
if (!ZCG(accel_directives).preload_user
|
||||
|| !*ZCG(accel_directives).preload_user) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0");
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
pw = getpwnam(ZCG(accel_directives).preload_user);
|
||||
if (pw == NULL) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (pw->pw_uid != euid) {
|
||||
pid = fork();
|
||||
if (pid == -1) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to fork()");
|
||||
return FAILURE;
|
||||
} else if (pid == 0) { /* children */
|
||||
if (setgid(pw->pw_gid) < 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
|
||||
exit(1);
|
||||
}
|
||||
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
|
||||
exit(1);
|
||||
}
|
||||
if (setuid(pw->pw_uid) < 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
|
||||
exit(1);
|
||||
}
|
||||
in_child = true;
|
||||
} else { /* parent */
|
||||
int status;
|
||||
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (ZCSG(preload_script)) {
|
||||
preload_load();
|
||||
}
|
||||
|
||||
zend_shared_alloc_unlock();
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ZCG(accel_directives).preload_user
|
||||
&& *ZCG(accel_directives).preload_user) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
|
||||
}
|
||||
}
|
||||
|
||||
sapi_module.activate = NULL;
|
||||
sapi_module.deactivate = NULL;
|
||||
sapi_module.register_server_variables = NULL;
|
||||
sapi_module.header_handler = preload_header_handler;
|
||||
sapi_module.send_headers = preload_send_headers;
|
||||
sapi_module.send_header = preload_send_header;
|
||||
sapi_module.getenv = NULL;
|
||||
sapi_module.ub_write = preload_ub_write;
|
||||
sapi_module.flush = preload_flush;
|
||||
|
||||
zend_interned_strings_switch_storage(1);
|
||||
|
||||
#ifdef ZEND_SIGNALS
|
||||
SIGG(reset) = false;
|
||||
#endif
|
||||
|
||||
orig_error_reporting = EG(error_reporting);
|
||||
EG(error_reporting) = 0;
|
||||
|
||||
rc = php_request_startup();
|
||||
|
||||
EG(error_reporting) = orig_error_reporting;
|
||||
|
||||
if (rc == SUCCESS) {
|
||||
bool orig_report_memleaks;
|
||||
|
||||
/* don't send headers */
|
||||
SG(headers_sent) = true;
|
||||
SG(request_info).no_headers = true;
|
||||
php_output_set_status(0);
|
||||
|
||||
ZCG(auto_globals_mask) = 0;
|
||||
ZCG(request_time) = (time_t)sapi_get_request_time();
|
||||
ZCG(cache_opline) = NULL;
|
||||
ZCG(cache_persistent_script) = NULL;
|
||||
ZCG(include_path_key_len) = 0;
|
||||
ZCG(include_path_check) = true;
|
||||
|
||||
ZCG(cwd) = NULL;
|
||||
ZCG(cwd_key_len) = 0;
|
||||
ZCG(cwd_check) = true;
|
||||
|
||||
if (accel_preload(ZCG(accel_directives).preload, in_child) != SUCCESS) {
|
||||
ret = FAILURE;
|
||||
}
|
||||
preload_flush(NULL);
|
||||
|
||||
orig_report_memleaks = PG(report_memleaks);
|
||||
PG(report_memleaks) = false;
|
||||
#ifdef ZEND_SIGNALS
|
||||
/* We may not have registered signal handlers due to SIGG(reset)=0, so
|
||||
* also disable the check that they are registered. */
|
||||
SIGG(check) = false;
|
||||
#endif
|
||||
php_request_shutdown(NULL); /* calls zend_shared_alloc_unlock(); */
|
||||
PG(report_memleaks) = orig_report_memleaks;
|
||||
} else {
|
||||
zend_shared_alloc_unlock();
|
||||
ret = FAILURE;
|
||||
}
|
||||
#ifdef ZEND_SIGNALS
|
||||
SIGG(reset) = old_reset_signals;
|
||||
#endif
|
||||
|
||||
sapi_module.activate = orig_activate;
|
||||
sapi_module.deactivate = orig_deactivate;
|
||||
sapi_module.register_server_variables = orig_register_server_variables;
|
||||
sapi_module.header_handler = orig_header_handler;
|
||||
sapi_module.send_headers = orig_send_headers;
|
||||
sapi_module.send_header = orig_send_header;
|
||||
sapi_module.getenv = orig_getenv;
|
||||
sapi_module.ub_write = orig_ub_write;
|
||||
sapi_module.flush = orig_flush;
|
||||
|
||||
sapi_activate();
|
||||
|
||||
if (in_child) {
|
||||
if (ret == SUCCESS) {
|
||||
exit(0);
|
||||
} else {
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
if (!(ZCG(accel_directives).preload && *ZCG(accel_directives).preload)) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
return SUCCESS;
|
||||
#ifdef ZEND_WIN32
|
||||
zend_accel_error_noreturn(ACCEL_LOG_ERROR, "Preloading is not supported on Windows");
|
||||
return FAILURE;
|
||||
#else /* ZEND_WIN32 */
|
||||
|
||||
if (UNEXPECTED(file_cache_only)) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "Preloading doesn't work in \"file_cache_only\" mode");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/* exclusive lock */
|
||||
zend_shared_alloc_lock();
|
||||
|
||||
if (ZCSG(preload_script)) {
|
||||
/* Preloading was done in another process */
|
||||
preload_load();
|
||||
zend_shared_alloc_unlock();
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
pid_t pid;
|
||||
if (accel_finish_startup_preload_subprocess(&pid) == FAILURE) {
|
||||
zend_shared_alloc_unlock();
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
if (pid == -1) { /* no subprocess was needed */
|
||||
return accel_finish_startup_preload(false);
|
||||
} else if (pid == 0) { /* subprocess */
|
||||
int ret = accel_finish_startup_preload(true);
|
||||
|
||||
exit(ret == SUCCESS ? 0 : 1);
|
||||
} else { /* parent */
|
||||
int status;
|
||||
|
||||
if (waitpid(pid, &status, 0) < 0) {
|
||||
zend_shared_alloc_unlock();
|
||||
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
|
||||
}
|
||||
|
||||
if (ZCSG(preload_script)) {
|
||||
preload_load();
|
||||
}
|
||||
|
||||
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
|
||||
return SUCCESS;
|
||||
} else {
|
||||
return FAILURE;
|
||||
}
|
||||
}
|
||||
#endif /* ZEND_WIN32 */
|
||||
}
|
||||
|
||||
ZEND_EXT_API zend_extension zend_extension_entry = {
|
||||
|
||||
Reference in New Issue
Block a user