diff options
-rw-r--r-- | Zend/zend.c | 73 | ||||
-rw-r--r-- | Zend/zend.h | 12 | ||||
-rw-r--r-- | Zend/zend_builtin_functions.c | 24 | ||||
-rw-r--r-- | Zend/zend_execute_API.c | 8 | ||||
-rw-r--r-- | Zend/zend_globals.h | 2 |
5 files changed, 114 insertions, 5 deletions
diff --git a/Zend/zend.c b/Zend/zend.c index 60494b7f46..5632a86587 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -40,7 +40,6 @@ ZEND_API zend_class_entry zend_standard_class_def; ZEND_API int (*zend_printf)(const char *format, ...); ZEND_API zend_write_func_t zend_write; -ZEND_API void (*zend_error)(int type, const char *format, ...); ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path); ZEND_API void (*zend_block_interruptions)(void); ZEND_API void (*zend_unblock_interruptions)(void); @@ -48,6 +47,12 @@ ZEND_API void (*zend_ticks_function)(int ticks); static void (*zend_message_dispatcher_p)(long message, void *data); static int (*zend_get_ini_entry_p)(char *name, uint name_length, zval *contents); +#if ZEND_NEW_ERROR_HANDLING +static void (*zend_error_cb)(int type, const char *format, ...); +#else +ZEND_API void (*zend_error_cb)(int type, const char *format, ...); +#endif + #ifdef ZTS ZEND_API int compiler_globals_id; ZEND_API int executor_globals_id; @@ -306,7 +311,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i #endif /* Set up utility functions and values */ - zend_error = utility_functions->error_function; + zend_error_cb = utility_functions->error_function; zend_printf = utility_functions->printf_function; zend_write = (zend_write_func_t) utility_functions->write_function; zend_fopen = utility_functions->fopen_function; @@ -483,3 +488,67 @@ ZEND_API int zend_get_ini_entry(char *name, uint name_length, zval *contents) return FAILURE; } } + + + +#if ZEND_NEW_ERROR_HANDLING + +#define ZEND_ERROR_BUFFER_SIZE 1024 + +ZEND_API void zend_error(int type, const char *format, ...) +{ + va_list args; + zval **params; + zval retval; + zval error_type, error_message; + ELS_FETCH(); + CLS_FETCH(); + + INIT_PZVAL(&error_message); + error_message.value.str.val = (char *) emalloc(ZEND_ERROR_BUFFER_SIZE); + + va_start(args, format); +/* error_message.value.str.len = vsnprintf(error_message->value.str.val, error_message->value.str.len-1, format, args); */ + error_message.value.str.len = vsprintf(error_message.value.str.val, format, args); + error_message.type = IS_STRING; + va_end(args); + + /* if we don't have a user defined error handler */ + if (!EG(user_error_handler)) { + zend_error_cb(type, error_message.value.str.val); + efree(error_message.value.str.val); + return; + } + + /* or the error may not be safe to handle in user-space */ + switch (type) { + case E_ERROR: + case E_PARSE: + case E_CORE_ERROR: + case E_CORE_WARNING: + case E_COMPILE_ERROR: + case E_COMPILE_WARNING: + zend_error_cb(type, error_message.value.str.val); + efree(error_message.value.str.val); + return; + } + + /* Handle the error in user space */ + + error_type.value.lval = type; + error_type.type = IS_LONG; + + params = (zval **) emalloc(sizeof(zval *)*2); + params[0] = &error_type; + params[1] = &error_message; + + if (call_user_function(CG(function_table), NULL, EG(user_error_handler), &retval, 2, params)==SUCCESS) { + } else { + /* The user error handler failed, use built-in error handler */ + zend_error_cb(type, error_message.value.str.val); + } + efree(params); + efree(error_message.value.str.val); +} + +#endif
\ No newline at end of file diff --git a/Zend/zend.h b/Zend/zend.h index 343ba1bb31..cff3f87792 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -315,12 +315,20 @@ ZEND_API extern char *empty_string; BEGIN_EXTERN_C() extern ZEND_API int (*zend_printf)(const char *format, ...); extern ZEND_API zend_write_func_t zend_write; -extern ZEND_API void (*zend_error)(int type, const char *format, ...); extern ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path); extern ZEND_API void (*zend_block_interruptions)(void); extern ZEND_API void (*zend_unblock_interruptions)(void); extern ZEND_API void (*zend_ticks_function)(int ticks); - + +#define ZEND_NEW_ERROR_HANDLING 0 + +#if ZEND_NEW_ERROR_HANDLING +ZEND_API void zend_error(int type, const char *format, ...); +#else +#define zend_error zend_error_cb +ZEND_API void (*zend_error_cb)(int type, const char *format, ...); +#endif + void zenderror(char *error); extern ZEND_API zend_class_entry zend_standard_class_def; diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index bed8b82b3a..e313123943 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -53,6 +53,7 @@ static ZEND_FUNCTION(get_class_vars); static ZEND_FUNCTION(get_object_vars); static ZEND_FUNCTION(get_class_methods); static ZEND_FUNCTION(user_error); +static ZEND_FUNCTION(set_user_error_handler); unsigned char first_arg_force_ref[] = { 1, BYREF_FORCE }; unsigned char first_arg_allow_ref[] = { 1, BYREF_ALLOW }; @@ -88,6 +89,7 @@ static zend_function_entry builtin_functions[] = { ZEND_FE(get_object_vars, NULL) ZEND_FE(get_class_methods, NULL) ZEND_FE(user_error, NULL) + ZEND_FE(set_user_error_handler, NULL) { NULL, NULL, NULL } }; @@ -732,3 +734,25 @@ ZEND_FUNCTION(user_error) RETURN_TRUE; } /* }}} */ + + +ZEND_FUNCTION(set_user_error_handler) +{ + zval **error_handler; + + if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &error_handler)==FAILURE) { + ZEND_WRONG_PARAM_COUNT(); + } + + convert_to_string_ex(error_handler); + if (EG(user_error_handler)) { + zval_dtor(EG(user_error_handler)); + } else { + ALLOC_ZVAL(EG(user_error_handler)); + } + + *EG(user_error_handler) = **error_handler; + zval_copy_ctor(EG(user_error_handler)); + + RETURN_TRUE; +} diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index cbdc121832..cf8a98f55b 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -115,6 +115,8 @@ void init_executor(CLS_D ELS_DC) zend_hash_init(&EG(included_files), 5, NULL, NULL, 0); EG(ticks_count) = 0; + + EG(user_error_handler) = NULL; } @@ -154,8 +156,12 @@ void shutdown_executor(ELS_D) signal(SIGSEGV, original_sigsegv_handler); #endif - zend_hash_destroy(&EG(included_files)); + + if (EG(user_error_handler)) { + zval_dtor(EG(user_error_handler)); + FREE_ZVAL(EG(user_error_handler)); + } } diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h index f41753d47c..2c76a8de06 100644 --- a/Zend/zend_globals.h +++ b/Zend/zend_globals.h @@ -179,6 +179,8 @@ struct _zend_executor_globals { zval *garbage[4]; int garbage_ptr; + zval *user_error_handler; + void *reserved[ZEND_MAX_RESERVED_RESOURCES]; #if SUPPORT_INTERACTIVE int interactive; |