@@ -121,6 +121,7 @@ zend_bool fallback_process = 0; /* process uses file cache fallback */
121121static zend_op_array * (* accelerator_orig_compile_file )(zend_file_handle * file_handle , int type );
122122static int (* accelerator_orig_zend_stream_open_function )(const char * filename , zend_file_handle * handle );
123123static zend_string * (* accelerator_orig_zend_resolve_path )(const char * filename , size_t filename_len );
124+ static void (* accelerator_orig_zend_error_cb )(int type , const char * error_filename , const uint32_t error_lineno , const char * format , va_list args );
124125static zif_handler orig_chdir = NULL ;
125126static ZEND_INI_MH ((* orig_include_path_on_modify )) = NULL ;
126127static int (* orig_post_startup_cb )(void );
@@ -1661,6 +1662,56 @@ static void zend_accel_init_auto_globals(void)
16611662 }
16621663}
16631664
1665+ static void persistent_error_cb (int type , const char * error_filename , const uint32_t error_lineno , const char * format , va_list args ) {
1666+ if (ZCG (record_warnings )) {
1667+ zend_recorded_warning * warning = emalloc (sizeof (zend_recorded_warning ));
1668+ va_list args_copy ;
1669+ warning -> type = type ;
1670+ warning -> error_lineno = error_lineno ;
1671+ warning -> error_filename = zend_string_init (error_filename , strlen (error_filename ), 0 );
1672+ va_copy (args_copy , args );
1673+ warning -> error_message = zend_vstrpprintf (0 , format , args_copy );
1674+ va_end (args_copy );
1675+
1676+ ZCG (num_warnings )++ ;
1677+ ZCG (warnings ) = erealloc (ZCG (warnings ), sizeof (zend_recorded_warning ) * ZCG (num_warnings ));
1678+ ZCG (warnings )[ZCG (num_warnings )- 1 ] = warning ;
1679+ }
1680+ accelerator_orig_zend_error_cb (type , error_filename , error_lineno , format , args );
1681+ }
1682+
1683+ /* Hack to get us a va_list to pass to zend_error_cb. */
1684+ static void replay_warning_helper (const zend_recorded_warning * warning , ...) {
1685+ va_list va ;
1686+ va_start (va , warning );
1687+ accelerator_orig_zend_error_cb (
1688+ warning -> type , ZSTR_VAL (warning -> error_filename ), warning -> error_lineno , "%s" , va );
1689+ va_end (va );
1690+ }
1691+
1692+ static void replay_warnings (zend_persistent_script * script ) {
1693+ for (uint32_t i = 0 ; i < script -> num_warnings ; i ++ ) {
1694+ zend_recorded_warning * warning = script -> warnings [i ];
1695+ replay_warning_helper (warning , ZSTR_VAL (warning -> error_message ));
1696+ }
1697+ }
1698+
1699+ static void free_recorded_warnings () {
1700+ if (!ZCG (num_warnings )) {
1701+ return ;
1702+ }
1703+
1704+ for (uint32_t i = 0 ; i < ZCG (num_warnings ); i ++ ) {
1705+ zend_recorded_warning * warning = ZCG (warnings )[i ];
1706+ zend_string_release (warning -> error_filename );
1707+ zend_string_release (warning -> error_message );
1708+ efree (warning );
1709+ }
1710+ efree (ZCG (warnings ));
1711+ ZCG (warnings ) = NULL ;
1712+ ZCG (num_warnings ) = 0 ;
1713+ }
1714+
16641715static zend_persistent_script * opcache_compile_file (zend_file_handle * file_handle , int type , const char * key , zend_op_array * * op_array_p )
16651716{
16661717 zend_persistent_script * new_persistent_script ;
@@ -1739,6 +1790,9 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17391790
17401791 /* Override them with ours */
17411792 ZVAL_UNDEF (& EG (user_error_handler ));
1793+ ZCG (record_warnings ) = ZCG (accel_directives ).record_warnings ;
1794+ ZCG (num_warnings ) = 0 ;
1795+ ZCG (warnings ) = NULL ;
17421796
17431797 zend_try {
17441798 orig_compiler_options = CG (compiler_options );
@@ -1761,9 +1815,11 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17611815 /* Restore originals */
17621816 CG (active_op_array ) = orig_active_op_array ;
17631817 EG (user_error_handler ) = orig_user_error_handler ;
1818+ ZCG (record_warnings ) = 0 ;
17641819
17651820 if (!op_array ) {
17661821 /* compilation failed */
1822+ free_recorded_warnings ();
17671823 if (do_bailout ) {
17681824 zend_bailout ();
17691825 }
@@ -1782,6 +1838,10 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
17821838 (op_array -> fn_flags & ZEND_ACC_EARLY_BINDING ) ?
17831839 zend_build_delayed_early_binding_list (op_array ) :
17841840 (uint32_t )-1 ;
1841+ new_persistent_script -> num_warnings = ZCG (num_warnings );
1842+ new_persistent_script -> warnings = ZCG (warnings );
1843+ ZCG (num_warnings ) = 0 ;
1844+ ZCG (warnings ) = NULL ;
17851845
17861846 efree (op_array ); /* we have valid persistent_script, so it's safe to free op_array */
17871847
@@ -1866,6 +1926,7 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
18661926 }
18671927 }
18681928 }
1929+ replay_warnings (persistent_script );
18691930 zend_file_handle_dtor (file_handle );
18701931
18711932 if (persistent_script -> ping_auto_globals_mask ) {
@@ -2187,6 +2248,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
21872248 }
21882249 }
21892250 }
2251+ replay_warnings (persistent_script );
21902252 zend_file_handle_dtor (file_handle );
21912253 from_shared_memory = 1 ;
21922254 }
@@ -3051,6 +3113,10 @@ static int accel_post_startup(void)
30513113 accelerator_orig_zend_resolve_path = zend_resolve_path ;
30523114 zend_resolve_path = persistent_zend_resolve_path ;
30533115
3116+ /* Override error callback, so we can store errors that occur during compilation */
3117+ accelerator_orig_zend_error_cb = zend_error_cb ;
3118+ zend_error_cb = persistent_error_cb ;
3119+
30543120 /* Override chdir() function */
30553121 if ((func = zend_hash_str_find_ptr (CG (function_table ), "chdir" , sizeof ("chdir" )- 1 )) != NULL &&
30563122 func -> type == ZEND_INTERNAL_FUNCTION ) {
0 commit comments