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;
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;
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;
zend_hash_destroy(GLOBAL_AUTO_GLOBALS_TABLE);
free(GLOBAL_AUTO_GLOBALS_TABLE);
+ zend_shutdown_error_notify_callbacks();
zend_shutdown_extensions();
free(zend_version_info);
}
}
-#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
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);
+ }
+}
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)
}
}
+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 */
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
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);
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);
}
}
+#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)
}
}
}
-#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 */
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