@@ -4572,206 +4572,227 @@ static void preload_send_header(sapi_header_struct *sapi_header, void *server_co
45724572{
45734573}
45744574
4575- static int accel_finish_startup (void )
4575+ #ifndef ZEND_WIN32
4576+ static int accel_finish_startup_preload (bool in_child )
45764577{
4577- if (!ZCG (enabled ) || !accel_startup_ok ) {
4578- return SUCCESS ;
4579- }
4578+ int ret = SUCCESS ;
4579+ int rc ;
4580+ int orig_error_reporting ;
4581+
4582+ int (* orig_activate )(void ) = sapi_module .activate ;
4583+ int (* orig_deactivate )(void ) = sapi_module .deactivate ;
4584+ void (* orig_register_server_variables )(zval * track_vars_array ) = sapi_module .register_server_variables ;
4585+ int (* orig_header_handler )(sapi_header_struct * sapi_header , sapi_header_op_enum op , sapi_headers_struct * sapi_headers ) = sapi_module .header_handler ;
4586+ int (* orig_send_headers )(sapi_headers_struct * sapi_headers ) = sapi_module .send_headers ;
4587+ void (* orig_send_header )(sapi_header_struct * sapi_header , void * server_context )= sapi_module .send_header ;
4588+ char * (* orig_getenv )(const char * name , size_t name_len ) = sapi_module .getenv ;
4589+ size_t (* orig_ub_write )(const char * str , size_t str_length ) = sapi_module .ub_write ;
4590+ void (* orig_flush )(void * server_context ) = sapi_module .flush ;
4591+ #ifdef ZEND_SIGNALS
4592+ bool old_reset_signals = SIGG (reset );
4593+ #endif
4594+
4595+ sapi_module .activate = NULL ;
4596+ sapi_module .deactivate = NULL ;
4597+ sapi_module .register_server_variables = NULL ;
4598+ sapi_module .header_handler = preload_header_handler ;
4599+ sapi_module .send_headers = preload_send_headers ;
4600+ sapi_module .send_header = preload_send_header ;
4601+ sapi_module .getenv = NULL ;
4602+ sapi_module .ub_write = preload_ub_write ;
4603+ sapi_module .flush = preload_flush ;
4604+
4605+ zend_interned_strings_switch_storage (1 );
45804606
4581- if (ZCG (accel_directives ).preload && * ZCG (accel_directives ).preload ) {
4582- #ifdef ZEND_WIN32
4583- zend_accel_error_noreturn (ACCEL_LOG_ERROR , "Preloading is not supported on Windows" );
4584- return FAILURE ;
4585- #else
4586- bool in_child = false;
4587- int ret = SUCCESS ;
4588- int rc ;
4589- int orig_error_reporting ;
4590-
4591- int (* orig_activate )(void ) = sapi_module .activate ;
4592- int (* orig_deactivate )(void ) = sapi_module .deactivate ;
4593- void (* orig_register_server_variables )(zval * track_vars_array ) = sapi_module .register_server_variables ;
4594- int (* orig_header_handler )(sapi_header_struct * sapi_header , sapi_header_op_enum op , sapi_headers_struct * sapi_headers ) = sapi_module .header_handler ;
4595- int (* orig_send_headers )(sapi_headers_struct * sapi_headers ) = sapi_module .send_headers ;
4596- void (* orig_send_header )(sapi_header_struct * sapi_header , void * server_context )= sapi_module .send_header ;
4597- char * (* orig_getenv )(const char * name , size_t name_len ) = sapi_module .getenv ;
4598- size_t (* orig_ub_write )(const char * str , size_t str_length ) = sapi_module .ub_write ;
4599- void (* orig_flush )(void * server_context ) = sapi_module .flush ;
46004607#ifdef ZEND_SIGNALS
4601- bool old_reset_signals = SIGG (reset );
4608+ SIGG (reset ) = false ;
46024609#endif
46034610
4604- if (UNEXPECTED (file_cache_only )) {
4605- zend_accel_error (ACCEL_LOG_WARNING , "Preloading doesn't work in \"file_cache_only\" mode" );
4606- return SUCCESS ;
4611+ orig_error_reporting = EG (error_reporting );
4612+ EG (error_reporting ) = 0 ;
4613+
4614+ rc = php_request_startup ();
4615+
4616+ EG (error_reporting ) = orig_error_reporting ;
4617+
4618+ if (rc == SUCCESS ) {
4619+ bool orig_report_memleaks ;
4620+
4621+ /* don't send headers */
4622+ SG (headers_sent ) = true;
4623+ SG (request_info ).no_headers = true;
4624+ php_output_set_status (0 );
4625+
4626+ ZCG (auto_globals_mask ) = 0 ;
4627+ ZCG (request_time ) = (time_t )sapi_get_request_time ();
4628+ ZCG (cache_opline ) = NULL ;
4629+ ZCG (cache_persistent_script ) = NULL ;
4630+ ZCG (include_path_key_len ) = 0 ;
4631+ ZCG (include_path_check ) = true;
4632+
4633+ ZCG (cwd ) = NULL ;
4634+ ZCG (cwd_key_len ) = 0 ;
4635+ ZCG (cwd_check ) = true;
4636+
4637+ if (accel_preload (ZCG (accel_directives ).preload , in_child ) != SUCCESS ) {
4638+ ret = FAILURE ;
46074639 }
4640+ preload_flush (NULL );
46084641
4609- /* exclusive lock */
4610- zend_shared_alloc_lock ();
4642+ orig_report_memleaks = PG (report_memleaks );
4643+ PG (report_memleaks ) = false;
4644+ #ifdef ZEND_SIGNALS
4645+ /* We may not have registered signal handlers due to SIGG(reset)=0, so
4646+ * also disable the check that they are registered. */
4647+ SIGG (check ) = false;
4648+ #endif
4649+ php_request_shutdown (NULL ); /* calls zend_shared_alloc_unlock(); */
4650+ PG (report_memleaks ) = orig_report_memleaks ;
4651+ } else {
4652+ zend_shared_alloc_unlock ();
4653+ ret = FAILURE ;
4654+ }
4655+ #ifdef ZEND_SIGNALS
4656+ SIGG (reset ) = old_reset_signals ;
4657+ #endif
46114658
4612- if (ZCSG (preload_script )) {
4613- /* Preloading was done in another process */
4614- preload_load ();
4615- zend_shared_alloc_unlock ();
4616- return SUCCESS ;
4659+ sapi_module .activate = orig_activate ;
4660+ sapi_module .deactivate = orig_deactivate ;
4661+ sapi_module .register_server_variables = orig_register_server_variables ;
4662+ sapi_module .header_handler = orig_header_handler ;
4663+ sapi_module .send_headers = orig_send_headers ;
4664+ sapi_module .send_header = orig_send_header ;
4665+ sapi_module .getenv = orig_getenv ;
4666+ sapi_module .ub_write = orig_ub_write ;
4667+ sapi_module .flush = orig_flush ;
4668+
4669+ sapi_activate ();
4670+
4671+ return ret ;
4672+ }
4673+
4674+ static int accel_finish_startup_preload_subprocess (pid_t * pid )
4675+ {
4676+ uid_t euid = geteuid ();
4677+ if (euid != 0 ) {
4678+ if (ZCG (accel_directives ).preload_user
4679+ && * ZCG (accel_directives ).preload_user ) {
4680+ zend_accel_error (ACCEL_LOG_WARNING , "\"opcache.preload_user\" is ignored" );
46174681 }
46184682
4619- uid_t euid = geteuid ();
4620- if (euid == 0 ) {
4621- pid_t pid ;
4622- struct passwd * pw ;
4683+ * pid = -1 ;
4684+ return SUCCESS ;
4685+ }
46234686
4624- if (!ZCG (accel_directives ).preload_user
4625- || !* ZCG (accel_directives ).preload_user ) {
4626- zend_shared_alloc_unlock ();
4627- zend_accel_error_noreturn (ACCEL_LOG_FATAL , "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0" );
4628- return FAILURE ;
4629- }
4687+ if (!ZCG (accel_directives ).preload_user
4688+ || !* ZCG (accel_directives ).preload_user ) {
46304689
4631- pw = getpwnam (ZCG (accel_directives ).preload_user );
4632- if (pw == NULL ) {
4633- zend_shared_alloc_unlock ();
4634- zend_accel_error_noreturn (ACCEL_LOG_FATAL , "Preloading failed to getpwnam(\"%s\")" , ZCG (accel_directives ).preload_user );
4635- return FAILURE ;
4636- }
46374690
4638- if (pw -> pw_uid != euid ) {
4639- pid = fork ();
4640- if (pid == -1 ) {
4641- zend_shared_alloc_unlock ();
4642- zend_accel_error_noreturn (ACCEL_LOG_FATAL , "Preloading failed to fork()" );
4643- return FAILURE ;
4644- } else if (pid == 0 ) { /* children */
4645- if (setgid (pw -> pw_gid ) < 0 ) {
4646- zend_accel_error (ACCEL_LOG_WARNING , "Preloading failed to setgid(%d)" , pw -> pw_gid );
4647- exit (1 );
4648- }
4649- if (initgroups (pw -> pw_name , pw -> pw_gid ) < 0 ) {
4650- zend_accel_error (ACCEL_LOG_WARNING , "Preloading failed to initgroups(\"%s\", %d)" , pw -> pw_name , pw -> pw_uid );
4651- exit (1 );
4652- }
4653- if (setuid (pw -> pw_uid ) < 0 ) {
4654- zend_accel_error (ACCEL_LOG_WARNING , "Preloading failed to setuid(%d)" , pw -> pw_uid );
4655- exit (1 );
4656- }
4657- in_child = true;
4658- } else { /* parent */
4659- int status ;
4691+ zend_shared_alloc_unlock ();
4692+ zend_accel_error_noreturn (ACCEL_LOG_FATAL , "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0" );
4693+ return FAILURE ;
4694+ }
46604695
4661- if (waitpid (pid , & status , 0 ) < 0 ) {
4662- zend_shared_alloc_unlock ();
4663- zend_accel_error_noreturn (ACCEL_LOG_FATAL , "Preloading failed to waitpid(%d)" , pid );
4664- return FAILURE ;
4665- }
4696+ struct passwd * pw = getpwnam (ZCG (accel_directives ).preload_user );
4697+ if (pw == NULL ) {
4698+ zend_shared_alloc_unlock ();
4699+ zend_accel_error_noreturn (ACCEL_LOG_FATAL , "Preloading failed to getpwnam(\"%s\")" , ZCG (accel_directives ).preload_user );
4700+ return FAILURE ;
4701+ }
46664702
4667- if (ZCSG (preload_script )) {
4668- preload_load ();
4669- }
4703+ if (pw -> pw_uid == euid ) {
4704+ * pid = -1 ;
4705+ return SUCCESS ;
4706+ }
46704707
4671- zend_shared_alloc_unlock ();
4672- if (WIFEXITED (status ) && WEXITSTATUS (status ) == 0 ) {
4673- return SUCCESS ;
4674- } else {
4675- return FAILURE ;
4676- }
4677- }
4678- }
4679- } else {
4680- if (ZCG (accel_directives ).preload_user
4681- && * ZCG (accel_directives ).preload_user ) {
4682- zend_accel_error (ACCEL_LOG_WARNING , "\"opcache.preload_user\" is ignored" );
4683- }
4708+ * pid = fork ();
4709+ if (* pid == -1 ) {
4710+ zend_shared_alloc_unlock ();
4711+ zend_accel_error_noreturn (ACCEL_LOG_FATAL , "Preloading failed to fork()" );
4712+ return FAILURE ;
4713+ }
4714+
4715+ if (* pid == 0 ) { /* children */
4716+ if (setgid (pw -> pw_gid ) < 0 ) {
4717+ zend_accel_error (ACCEL_LOG_WARNING , "Preloading failed to setgid(%d)" , pw -> pw_gid );
4718+ exit (1 );
4719+ }
4720+ if (initgroups (pw -> pw_name , pw -> pw_gid ) < 0 ) {
4721+ zend_accel_error (ACCEL_LOG_WARNING , "Preloading failed to initgroups(\"%s\", %d)" , pw -> pw_name , pw -> pw_uid );
4722+ exit (1 );
4723+ }
4724+ if (setuid (pw -> pw_uid ) < 0 ) {
4725+ zend_accel_error (ACCEL_LOG_WARNING , "Preloading failed to setuid(%d)" , pw -> pw_uid );
4726+ exit (1 );
46844727 }
4728+ }
46854729
4686- sapi_module .activate = NULL ;
4687- sapi_module .deactivate = NULL ;
4688- sapi_module .register_server_variables = NULL ;
4689- sapi_module .header_handler = preload_header_handler ;
4690- sapi_module .send_headers = preload_send_headers ;
4691- sapi_module .send_header = preload_send_header ;
4692- sapi_module .getenv = NULL ;
4693- sapi_module .ub_write = preload_ub_write ;
4694- sapi_module .flush = preload_flush ;
4730+ return SUCCESS ;
4731+ }
4732+ #endif /* ZEND_WIN32 */
46954733
4696- zend_interned_strings_switch_storage (1 );
4734+ static int accel_finish_startup (void )
4735+ {
4736+ if (!ZCG (enabled ) || !accel_startup_ok ) {
4737+ return SUCCESS ;
4738+ }
46974739
4698- #ifdef ZEND_SIGNALS
4699- SIGG ( reset ) = false ;
4700- #endif
4740+ if (!( ZCG ( accel_directives ). preload && * ZCG ( accel_directives ). preload )) {
4741+ return SUCCESS ;
4742+ }
47014743
4702- orig_error_reporting = EG (error_reporting );
4703- EG (error_reporting ) = 0 ;
4744+ #ifdef ZEND_WIN32
4745+ zend_accel_error_noreturn (ACCEL_LOG_ERROR , "Preloading is not supported on Windows" );
4746+ return FAILURE ;
4747+ #else /* ZEND_WIN32 */
47044748
4705- rc = php_request_startup ();
4749+ if (UNEXPECTED (file_cache_only )) {
4750+ zend_accel_error (ACCEL_LOG_WARNING , "Preloading doesn't work in \"file_cache_only\" mode" );
4751+ return SUCCESS ;
4752+ }
47064753
4707- EG (error_reporting ) = orig_error_reporting ;
4754+ /* exclusive lock */
4755+ zend_shared_alloc_lock ();
47084756
4709- if (rc == SUCCESS ) {
4710- bool orig_report_memleaks ;
4757+ if (ZCSG (preload_script )) {
4758+ /* Preloading was done in another process */
4759+ preload_load ();
4760+ zend_shared_alloc_unlock ();
4761+ return SUCCESS ;
4762+ }
47114763
4712- /* don't send headers */
4713- SG (headers_sent ) = true;
4714- SG (request_info ).no_headers = true;
4715- php_output_set_status (0 );
47164764
4717- ZCG (auto_globals_mask ) = 0 ;
4718- ZCG (request_time ) = (time_t )sapi_get_request_time ();
4719- ZCG (cache_opline ) = NULL ;
4720- ZCG (cache_persistent_script ) = NULL ;
4721- ZCG (include_path_key_len ) = 0 ;
4722- ZCG (include_path_check ) = true;
4765+ pid_t pid ;
4766+ if (accel_finish_startup_preload_subprocess (& pid ) == FAILURE ) {
4767+ zend_shared_alloc_unlock ();
4768+ return FAILURE ;
4769+ }
47234770
4724- ZCG (cwd ) = NULL ;
4725- ZCG (cwd_key_len ) = 0 ;
4726- ZCG (cwd_check ) = true;
4771+ if (pid == -1 ) { /* no subprocess was needed */
4772+ return accel_finish_startup_preload (false);
4773+ } else if (pid == 0 ) { /* subprocess */
4774+ int ret = accel_finish_startup_preload (true);
47274775
4728- if (accel_preload (ZCG (accel_directives ).preload , in_child ) != SUCCESS ) {
4729- ret = FAILURE ;
4730- }
4731- preload_flush (NULL );
4776+ exit (ret == SUCCESS ? 0 : 1 );
4777+ } else { /* parent */
4778+ int status ;
47324779
4733- orig_report_memleaks = PG (report_memleaks );
4734- PG (report_memleaks ) = false;
4735- #ifdef ZEND_SIGNALS
4736- /* We may not have registered signal handlers due to SIGG(reset)=0, so
4737- * also disable the check that they are registered. */
4738- SIGG (check ) = false;
4739- #endif
4740- php_request_shutdown (NULL ); /* calls zend_shared_alloc_unlock(); */
4741- PG (report_memleaks ) = orig_report_memleaks ;
4742- } else {
4780+ if (waitpid (pid , & status , 0 ) < 0 ) {
47434781 zend_shared_alloc_unlock ();
4744- ret = FAILURE ;
4782+ zend_accel_error_noreturn ( ACCEL_LOG_FATAL , "Preloading failed to waitpid(%d)" , pid ) ;
47454783 }
4746- #ifdef ZEND_SIGNALS
4747- SIGG (reset ) = old_reset_signals ;
4748- #endif
47494784
4750- sapi_module .activate = orig_activate ;
4751- sapi_module .deactivate = orig_deactivate ;
4752- sapi_module .register_server_variables = orig_register_server_variables ;
4753- sapi_module .header_handler = orig_header_handler ;
4754- sapi_module .send_headers = orig_send_headers ;
4755- sapi_module .send_header = orig_send_header ;
4756- sapi_module .getenv = orig_getenv ;
4757- sapi_module .ub_write = orig_ub_write ;
4758- sapi_module .flush = orig_flush ;
4759-
4760- sapi_activate ();
4761-
4762- if (in_child ) {
4763- if (ret == SUCCESS ) {
4764- exit (0 );
4765- } else {
4766- exit (2 );
4767- }
4785+ if (ZCSG (preload_script )) {
4786+ preload_load ();
47684787 }
47694788
4770- return ret ;
4771- #endif
4789+ if (WIFEXITED (status ) && WEXITSTATUS (status ) == 0 ) {
4790+ return SUCCESS ;
4791+ } else {
4792+ return FAILURE ;
4793+ }
47724794 }
4773-
4774- return SUCCESS ;
4795+ #endif /* ZEND_WIN32 */
47754796}
47764797
47774798ZEND_EXT_API zend_extension zend_extension_entry = {
0 commit comments