]> granicus.if.org Git - php/commitdiff
Introduce error notification callbacks that are run independant of zend_error_cb
authorBenjamin Eberlei <kontakt@beberlei.de>
Mon, 27 Apr 2020 06:20:56 +0000 (08:20 +0200)
committerBenjamin Eberlei <kontakt@beberlei.de>
Fri, 17 Jul 2020 13:08:11 +0000 (15:08 +0200)
Zend/zend.c
Zend/zend.h
Zend/zend_dtrace.c
Zend/zend_dtrace.h
Zend/zend_exceptions.c
main/main.c

index 2765f8c3ead2251cae059ff9660f40a175c0cc98..7177f13c578e4bf873263ed40c0706aaec1ce9a0 100644 (file)
@@ -61,6 +61,8 @@ ZEND_TSRMLS_CACHE_DEFINE()
 ZEND_API zend_utility_values zend_uv;
 ZEND_API zend_bool zend_dtrace_enabled;
 
+zend_llist zend_error_notify_callbacks;
+
 /* version information */
 static char *zend_version_info;
 static uint32_t zend_version_info_length;
@@ -815,6 +817,7 @@ int zend_startup(zend_utility_functions *utility_functions) /* {{{ */
 
        zend_startup_strtod();
        zend_startup_extensions_mechanism();
+       zend_startup_error_notify_callbacks();
 
        /* Set up utility functions and values */
        zend_error_cb = utility_functions->error_function;
@@ -846,6 +849,8 @@ int zend_startup(zend_utility_functions *utility_functions) /* {{{ */
                        zend_compile_file = dtrace_compile_file;
                        zend_execute_ex = dtrace_execute_ex;
                        zend_execute_internal = dtrace_execute_internal;
+
+                       zend_register_error_notify_callback(dtrace_error_notify_cb);
                } else {
                        zend_compile_file = compile_file;
                        zend_execute_ex = execute_ex;
@@ -1075,6 +1080,7 @@ void zend_shutdown(void) /* {{{ */
        zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
        free(GLOBAL_AUTO_GLOBALS_TABLE);
 
+       zend_shutdown_error_notify_callbacks();
        zend_shutdown_extensions();
        free(zend_version_info);
 
@@ -1311,11 +1317,7 @@ static ZEND_COLD void zend_error_impl(
                }
        }
 
-#ifdef HAVE_DTRACE
-       if (DTRACE_ERROR_ENABLED()) {
-               DTRACE_ERROR(ZSTR_VAL(message), (char *)error_filename, error_lineno);
-       }
-#endif /* HAVE_DTRACE */
+       zend_error_notify_all_callbacks(type, error_filename, error_lineno, message);
 
        /* if we don't have a user defined error handler */
        if (Z_TYPE(EG(user_error_handler)) == IS_UNDEF
@@ -1771,3 +1773,29 @@ ZEND_API void zend_map_ptr_extend(size_t last)
                CG(map_ptr_last) = last;
        }
 }
+
+void zend_startup_error_notify_callbacks()
+{
+       zend_llist_init(&zend_error_notify_callbacks, sizeof(zend_error_notify_cb), NULL, 1);
+}
+
+void zend_shutdown_error_notify_callbacks()
+{
+       zend_llist_destroy(&zend_error_notify_callbacks);
+}
+
+void zend_register_error_notify_callback(zend_error_notify_cb cb)
+{
+       zend_llist_add_element(&zend_error_notify_callbacks, &cb);
+}
+
+void zend_error_notify_all_callbacks(int type, const char *error_filename, uint32_t error_lineno, zend_string *message)
+{
+       zend_llist_element *element;
+       zend_error_notify_cb callback;
+
+       for (element = zend_error_notify_callbacks.head; element; element = element->next) {
+               callback = *(zend_error_notify_cb *) (element->data);
+               callback(type, error_filename, error_lineno, message);
+       }
+}
index 4fe89fcacc809936a20e9ae1224e32cf730192c3..956d4532df7957cae1a0f3ee1531995510efe1c8 100644 (file)
@@ -351,6 +351,16 @@ ZEND_API void zend_save_error_handling(zend_error_handling *current);
 ZEND_API void zend_replace_error_handling(zend_error_handling_t error_handling, zend_class_entry *exception_class, zend_error_handling *current);
 ZEND_API void zend_restore_error_handling(zend_error_handling *saved);
 
+typedef void (*zend_error_notify_cb)(int type, const char *error_filename, uint32_t error_lineno, zend_string *message);
+
+BEGIN_EXTERN_C()
+
+void zend_register_error_notify_callback(zend_error_notify_cb callback);
+void zend_startup_error_notify_callbacks();
+void zend_shutdown_error_notify_callbacks();
+void zend_error_notify_all_callbacks(int type, const char *error_filename, uint32_t error_lineno, zend_string *message);
+END_EXTERN_C()
+
 #define DEBUG_BACKTRACE_PROVIDE_OBJECT (1<<0)
 #define DEBUG_BACKTRACE_IGNORE_ARGS    (1<<1)
 
index 750fb686c8b0e568d0fc0a3744d956fe458f08be..935421121e3f53c5765f25e50e0d74b5fd14317b 100644 (file)
@@ -109,6 +109,13 @@ ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *ret
        }
 }
 
+void dtrace_error_notify_cb(int type, const char *error_filename, uint32_t error_lineno, zend_string *message)
+{
+       if (DTRACE_ERROR_ENABLED()) {
+               DTRACE_ERROR(ZSTR_VAL(message), (char *)error_filename, error_lineno);
+       }
+}
+
 /* }}} */
 
 #endif /* HAVE_DTRACE */
index c4fedadd40dfbafa6bfbb17c498cf452b21d05e0..84c7379e3781dc48d666b090e7f03d5569515ac5 100644 (file)
@@ -37,6 +37,8 @@ ZEND_API void dtrace_execute_ex(zend_execute_data *execute_data);
 ZEND_API void dtrace_execute_internal(zend_execute_data *execute_data, zval *return_value);
 #include <zend_dtrace_gen.h>
 
+void dtrace_error_notify_cb(int type, const char *error_filename, uint32_t error_lineno, zend_string *message);
+
 #endif /* HAVE_DTRACE */
 
 #ifdef __cplusplus
index e46e18f1d3a9c4ef3ad0eec7a1da6c7494e9b035..24bfa9e41afb482cc2671b872aaaa36c24af2e38 100644 (file)
@@ -893,6 +893,7 @@ static void zend_error_va(int type, const char *file, uint32_t lineno, const cha
        va_list args;
        va_start(args, format);
        zend_string *message = zend_vstrpprintf(0, format, args);
+       zend_error_notify_all_callbacks(type, file, lineno, message);
        zend_error_cb(type, file, lineno, message);
        zend_string_release(message);
        va_end(args);
@@ -913,10 +914,10 @@ ZEND_API ZEND_COLD int zend_exception_error(zend_object *ex, int severity) /* {{
                zend_string *message = zval_get_string(GET_PROPERTY(&exception, ZEND_STR_MESSAGE));
                zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, ZEND_STR_FILE));
                zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, ZEND_STR_LINE));
+               int type = (ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR) | E_DONT_BAIL;
 
-               zend_error_cb(
-                       (ce_exception == zend_ce_parse_error ? E_PARSE : E_COMPILE_ERROR) | E_DONT_BAIL,
-                       ZSTR_VAL(file), line, message);
+               zend_error_notify_all_callbacks(type, ZSTR_VAL(file), line, message);
+               zend_error_cb(type, ZSTR_VAL(file), line, message);
 
                zend_string_release_ex(file, 0);
                zend_string_release_ex(message, 0);
index 3b052d8b6e3be887333e9830869b9fd42ab8969d..9c0c8c11b9b267827f83dc0ffa5055f22a7f0f75 100644 (file)
@@ -1175,6 +1175,31 @@ static void clear_last_error() {
        }
 }
 
+#if ZEND_DEBUG
+/* {{{ report_zend_debug_error_notify_cb */
+static void report_zend_debug_error_notify_cb(int type, const char *error_filename, uint32_t error_lineno, zend_string *message)
+{
+       if (PG(report_zend_debug)) {
+               zend_bool trigger_break;
+
+               switch (type) {
+                       case E_ERROR:
+                       case E_CORE_ERROR:
+                       case E_COMPILE_ERROR:
+                       case E_USER_ERROR:
+                               trigger_break=1;
+                               break;
+                       default:
+                               trigger_break=0;
+                               break;
+               }
+
+               zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s", error_filename, error_lineno, ZSTR_VAL(message));
+       }
+}
+/* }}} */
+#endif
+
 /* {{{ php_error_cb
  extended error handling function */
 static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, const uint32_t error_lineno, zend_string *message)
@@ -1330,24 +1355,6 @@ static ZEND_COLD void php_error_cb(int orig_type, const char *error_filename, co
                                }
                        }
                }
-#if ZEND_DEBUG
-               if (PG(report_zend_debug)) {
-                       zend_bool trigger_break;
-
-                       switch (type) {
-                               case E_ERROR:
-                               case E_CORE_ERROR:
-                               case E_COMPILE_ERROR:
-                               case E_USER_ERROR:
-                                       trigger_break=1;
-                                       break;
-                               default:
-                                       trigger_break=0;
-                                       break;
-                       }
-                       zend_output_debug_string(trigger_break, "%s(%" PRIu32 ") : %s - %s", error_filename, error_lineno, error_type_str, ZSTR_VAL(message));
-               }
-#endif
        }
 
        /* Bail out if we can't recover */
@@ -2083,6 +2090,10 @@ int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_mod
        zend_startup(&zuf);
        zend_update_current_locale();
 
+#if ZEND_DEBUG
+       zend_register_error_notify_callback(report_zend_debug_error_notify_cb);
+#endif
+
 #if HAVE_TZSET
        tzset();
 #endif