mirror of
https://github.com/php/php-src.git
synced 2025-08-16 22:18:50 +02:00
@- Added set_exception_handler() function for registering a global,
@ catch-all exception handling function (Stig) - Added set_exception_handler() function for registering a global, catch-all exception handling function (Stig)
This commit is contained in:
parent
197c300860
commit
04788f9503
5 changed files with 152 additions and 8 deletions
56
Zend/zend.c
56
Zend/zend.c
|
@ -45,6 +45,7 @@ BOOL WINAPI IsDebuggerPresent(VOID);
|
||||||
|
|
||||||
/* true multithread-shared globals */
|
/* true multithread-shared globals */
|
||||||
ZEND_API zend_class_entry *zend_standard_class_def = NULL;
|
ZEND_API zend_class_entry *zend_standard_class_def = NULL;
|
||||||
|
ZEND_API zend_class_entry *zend_exception_class_def = NULL;
|
||||||
ZEND_API int (*zend_printf)(const char *format, ...);
|
ZEND_API int (*zend_printf)(const char *format, ...);
|
||||||
ZEND_API zend_write_func_t zend_write;
|
ZEND_API zend_write_func_t zend_write;
|
||||||
ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
|
ZEND_API FILE *(*zend_fopen)(const char *filename, char **opened_path);
|
||||||
|
@ -271,6 +272,33 @@ static void register_standard_class(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void register_exception_class(void)
|
||||||
|
{
|
||||||
|
zend_exception_class_def = malloc(sizeof(zend_class_entry));
|
||||||
|
|
||||||
|
zend_exception_class_def->type = ZEND_INTERNAL_CLASS;
|
||||||
|
zend_exception_class_def->name_length = sizeof("Exception") - 1;
|
||||||
|
zend_exception_class_def->name = zend_strndup("Exception", zend_exception_class_def->name_length);
|
||||||
|
zend_exception_class_def->parent = NULL;
|
||||||
|
zend_hash_init_ex(&zend_exception_class_def->default_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||||
|
zend_hash_init_ex(&zend_exception_class_def->private_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||||
|
zend_hash_init_ex(&zend_exception_class_def->protected_properties, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||||
|
zend_exception_class_def->static_members = (HashTable *) malloc(sizeof(HashTable));
|
||||||
|
zend_hash_init_ex(zend_exception_class_def->static_members, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||||
|
zend_hash_init_ex(&zend_exception_class_def->constants_table, 0, NULL, ZVAL_PTR_DTOR, 1, 0);
|
||||||
|
zend_hash_init_ex(&zend_exception_class_def->class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
|
||||||
|
zend_hash_init_ex(&zend_exception_class_def->function_table, 0, NULL, ZEND_FUNCTION_DTOR, 1, 0);
|
||||||
|
zend_exception_class_def->constructor = NULL;
|
||||||
|
zend_exception_class_def->destructor = NULL;
|
||||||
|
zend_exception_class_def->clone = NULL;
|
||||||
|
zend_exception_class_def->handle_function_call = NULL;
|
||||||
|
zend_exception_class_def->handle_property_get = NULL;
|
||||||
|
zend_exception_class_def->handle_property_set = NULL;
|
||||||
|
zend_exception_class_def->refcount = 1;
|
||||||
|
zend_hash_add(GLOBAL_CLASS_TABLE, "exception", sizeof("exception"), &zend_exception_class_def, sizeof(zend_class_entry *), NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void zend_set_default_compile_time_values(TSRMLS_D)
|
static void zend_set_default_compile_time_values(TSRMLS_D)
|
||||||
{
|
{
|
||||||
/* default compile-time values */
|
/* default compile-time values */
|
||||||
|
@ -331,6 +359,7 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals TSRMLS
|
||||||
zend_init_rsrc_plist(TSRMLS_C);
|
zend_init_rsrc_plist(TSRMLS_C);
|
||||||
EG(lambda_count)=0;
|
EG(lambda_count)=0;
|
||||||
EG(user_error_handler) = NULL;
|
EG(user_error_handler) = NULL;
|
||||||
|
EG(user_exception_handler) = NULL;
|
||||||
EG(in_execution) = 0;
|
EG(in_execution) = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,9 +472,11 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
|
||||||
zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0);
|
zend_hash_init_ex(GLOBAL_AUTO_GLOBALS_TABLE, 8, NULL, NULL, 1, 0);
|
||||||
|
|
||||||
register_standard_class();
|
register_standard_class();
|
||||||
|
register_exception_class();
|
||||||
zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
|
zend_hash_init_ex(&module_registry, 50, NULL, ZEND_MODULE_DTOR, 1, 0);
|
||||||
zend_init_rsrc_list_dtors();
|
zend_init_rsrc_list_dtors();
|
||||||
|
|
||||||
|
|
||||||
/* This zval can be used to initialize allocate zval's to an uninit'ed value */
|
/* This zval can be used to initialize allocate zval's to an uninit'ed value */
|
||||||
zval_used_for_init.is_ref = 0;
|
zval_used_for_init.is_ref = 0;
|
||||||
zval_used_for_init.refcount = 1;
|
zval_used_for_init.refcount = 1;
|
||||||
|
@ -471,6 +502,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions, i
|
||||||
zend_startup_constants();
|
zend_startup_constants();
|
||||||
zend_set_default_compile_time_values(TSRMLS_C);
|
zend_set_default_compile_time_values(TSRMLS_C);
|
||||||
EG(user_error_handler) = NULL;
|
EG(user_error_handler) = NULL;
|
||||||
|
EG(user_exception_handler) = NULL;
|
||||||
#endif
|
#endif
|
||||||
zend_register_standard_constants(TSRMLS_C);
|
zend_register_standard_constants(TSRMLS_C);
|
||||||
|
|
||||||
|
@ -828,8 +860,32 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
|
||||||
EG(return_value_ptr_ptr) = retval ? retval : &local_retval;
|
EG(return_value_ptr_ptr) = retval ? retval : &local_retval;
|
||||||
zend_execute(EG(active_op_array) TSRMLS_CC);
|
zend_execute(EG(active_op_array) TSRMLS_CC);
|
||||||
if (EG(exception)) {
|
if (EG(exception)) {
|
||||||
|
#if 1 /* support set_exception_handler() */
|
||||||
|
if (EG(user_exception_handler)) {
|
||||||
|
zval *orig_user_exception_handler;
|
||||||
|
zval ***params, *retval2;
|
||||||
|
params = (zval ***)emalloc(sizeof(zval **));
|
||||||
|
params[0] = &EG(exception);
|
||||||
|
orig_user_exception_handler = EG(user_exception_handler);
|
||||||
|
if (call_user_function_ex(CG(function_table), NULL, orig_user_exception_handler, &retval2, 1, params, 1, NULL TSRMLS_CC) == SUCCESS) {
|
||||||
|
zval_ptr_dtor(&retval2);
|
||||||
|
}
|
||||||
|
efree(params);
|
||||||
|
zval_ptr_dtor(&EG(exception));
|
||||||
|
EG(exception) = NULL;
|
||||||
|
} else {
|
||||||
|
zval_ptr_dtor(&EG(exception));
|
||||||
|
EG(exception) = NULL;
|
||||||
|
zend_error(E_ERROR, "Uncaught exception!");
|
||||||
|
}
|
||||||
|
if (!retval) {
|
||||||
|
zval_ptr_dtor(EG(return_value_ptr_ptr));
|
||||||
|
local_retval = NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
zval_ptr_dtor(&EG(exception));
|
zval_ptr_dtor(&EG(exception));
|
||||||
zend_error(E_ERROR, "Uncaught exception!");
|
zend_error(E_ERROR, "Uncaught exception!");
|
||||||
|
#endif
|
||||||
} else if (!retval) {
|
} else if (!retval) {
|
||||||
zval_ptr_dtor(EG(return_value_ptr_ptr));
|
zval_ptr_dtor(EG(return_value_ptr_ptr));
|
||||||
local_retval = NULL;
|
local_retval = NULL;
|
||||||
|
|
|
@ -56,6 +56,8 @@ static ZEND_FUNCTION(get_class_methods);
|
||||||
static ZEND_FUNCTION(trigger_error);
|
static ZEND_FUNCTION(trigger_error);
|
||||||
static ZEND_FUNCTION(set_error_handler);
|
static ZEND_FUNCTION(set_error_handler);
|
||||||
static ZEND_FUNCTION(restore_error_handler);
|
static ZEND_FUNCTION(restore_error_handler);
|
||||||
|
static ZEND_FUNCTION(set_exception_handler);
|
||||||
|
static ZEND_FUNCTION(restore_exception_handler);
|
||||||
static ZEND_FUNCTION(get_declared_classes);
|
static ZEND_FUNCTION(get_declared_classes);
|
||||||
static ZEND_FUNCTION(get_defined_functions);
|
static ZEND_FUNCTION(get_defined_functions);
|
||||||
static ZEND_FUNCTION(get_defined_vars);
|
static ZEND_FUNCTION(get_defined_vars);
|
||||||
|
@ -108,6 +110,8 @@ static zend_function_entry builtin_functions[] = {
|
||||||
ZEND_FALIAS(user_error, trigger_error, NULL)
|
ZEND_FALIAS(user_error, trigger_error, NULL)
|
||||||
ZEND_FE(set_error_handler, NULL)
|
ZEND_FE(set_error_handler, NULL)
|
||||||
ZEND_FE(restore_error_handler, NULL)
|
ZEND_FE(restore_error_handler, NULL)
|
||||||
|
ZEND_FE(set_exception_handler, NULL)
|
||||||
|
ZEND_FE(restore_exception_handler, NULL)
|
||||||
ZEND_FE(get_declared_classes, NULL)
|
ZEND_FE(get_declared_classes, NULL)
|
||||||
ZEND_FE(get_defined_functions, NULL)
|
ZEND_FE(get_defined_functions, NULL)
|
||||||
ZEND_FE(get_defined_vars, NULL)
|
ZEND_FE(get_defined_vars, NULL)
|
||||||
|
@ -958,6 +962,59 @@ ZEND_FUNCTION(restore_error_handler)
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
|
/* {{{ proto string set_exception_handler(string exception_handler)
|
||||||
|
Sets a user-defined exception handler function. Returns the previously defined exception handler, or false on error */
|
||||||
|
ZEND_FUNCTION(set_exception_handler)
|
||||||
|
{
|
||||||
|
zval **exception_handler;
|
||||||
|
zend_bool had_orig_exception_handler=0;
|
||||||
|
|
||||||
|
if (ZEND_NUM_ARGS()!=1 || zend_get_parameters_ex(1, &exception_handler)==FAILURE) {
|
||||||
|
ZEND_WRONG_PARAM_COUNT();
|
||||||
|
}
|
||||||
|
|
||||||
|
convert_to_string_ex(exception_handler);
|
||||||
|
if (EG(user_exception_handler)) {
|
||||||
|
had_orig_exception_handler = 1;
|
||||||
|
*return_value = *EG(user_exception_handler);
|
||||||
|
zval_copy_ctor(return_value);
|
||||||
|
zend_ptr_stack_push(&EG(user_exception_handlers), EG(user_exception_handler));
|
||||||
|
}
|
||||||
|
ALLOC_ZVAL(EG(user_exception_handler));
|
||||||
|
|
||||||
|
if (Z_STRLEN_PP(exception_handler)==0) { /* unset user-defined handler */
|
||||||
|
FREE_ZVAL(EG(user_exception_handler));
|
||||||
|
EG(user_exception_handler) = NULL;
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
*EG(user_exception_handler) = **exception_handler;
|
||||||
|
zval_copy_ctor(EG(user_exception_handler));
|
||||||
|
|
||||||
|
if (!had_orig_exception_handler) {
|
||||||
|
RETURN_NULL();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
|
/* {{{ proto void restore_exception_handler(void)
|
||||||
|
Restores the previously defined exception handler function */
|
||||||
|
ZEND_FUNCTION(restore_exception_handler)
|
||||||
|
{
|
||||||
|
if (EG(user_exception_handler)) {
|
||||||
|
zval_ptr_dtor(&EG(user_exception_handler));
|
||||||
|
}
|
||||||
|
if (zend_ptr_stack_num_elements(&EG(user_exception_handlers))==0) {
|
||||||
|
EG(user_exception_handler) = NULL;
|
||||||
|
} else {
|
||||||
|
EG(user_exception_handler) = zend_ptr_stack_pop(&EG(user_exception_handlers));
|
||||||
|
}
|
||||||
|
RETURN_TRUE;
|
||||||
|
}
|
||||||
|
/* }}} */
|
||||||
|
|
||||||
|
|
||||||
static int copy_class_name(zend_class_entry **pce, int num_args, va_list args, zend_hash_key *hash_key)
|
static int copy_class_name(zend_class_entry **pce, int num_args, va_list args, zend_hash_key *hash_key)
|
||||||
{
|
{
|
||||||
zval *array = va_arg(args, zval *);
|
zval *array = va_arg(args, zval *);
|
||||||
|
@ -1199,7 +1256,6 @@ ZEND_FUNCTION(debug_backtrace)
|
||||||
char *function_name;
|
char *function_name;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *class_name;
|
char *class_name;
|
||||||
zend_uint class_name_length;
|
|
||||||
zval *stack_frame;
|
zval *stack_frame;
|
||||||
|
|
||||||
ptr = EG(current_execute_data);
|
ptr = EG(current_execute_data);
|
||||||
|
@ -1217,7 +1273,6 @@ ZEND_FUNCTION(debug_backtrace)
|
||||||
|
|
||||||
if (ptr->object) {
|
if (ptr->object) {
|
||||||
class_name = Z_OBJCE(*ptr->object)->name;
|
class_name = Z_OBJCE(*ptr->object)->name;
|
||||||
class_name_length = Z_OBJCE(*ptr->object)->name_length;
|
|
||||||
}
|
}
|
||||||
if (ptr->function_state.function->common.scope) {
|
if (ptr->function_state.function->common.scope) {
|
||||||
class_name = ptr->function_state.function->common.scope->name;
|
class_name = ptr->function_state.function->common.scope->name;
|
||||||
|
@ -1294,3 +1349,11 @@ ZEND_FUNCTION(get_extension_funcs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Local variables:
|
||||||
|
* tab-width: 4
|
||||||
|
* c-basic-offset: 4
|
||||||
|
* indent-tabs-mode: t
|
||||||
|
* End:
|
||||||
|
*/
|
||||||
|
|
|
@ -158,6 +158,7 @@ void init_executor(TSRMLS_D)
|
||||||
EG(user_error_handler) = NULL;
|
EG(user_error_handler) = NULL;
|
||||||
|
|
||||||
zend_ptr_stack_init(&EG(user_error_handlers));
|
zend_ptr_stack_init(&EG(user_error_handlers));
|
||||||
|
zend_ptr_stack_init(&EG(user_exception_handlers));
|
||||||
|
|
||||||
EG(orig_error_reporting) = EG(error_reporting);
|
EG(orig_error_reporting) = EG(error_reporting);
|
||||||
zend_objects_store_init(&EG(objects_store), 1024);
|
zend_objects_store_init(&EG(objects_store), 1024);
|
||||||
|
@ -232,9 +233,17 @@ void shutdown_executor(TSRMLS_D)
|
||||||
FREE_ZVAL(EG(user_error_handler));
|
FREE_ZVAL(EG(user_error_handler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (EG(user_exception_handler)) {
|
||||||
|
zval_dtor(EG(user_exception_handler));
|
||||||
|
FREE_ZVAL(EG(user_exception_handler));
|
||||||
|
}
|
||||||
|
|
||||||
zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
|
zend_ptr_stack_clean(&EG(user_error_handlers), ZVAL_DESTRUCTOR, 1);
|
||||||
zend_ptr_stack_destroy(&EG(user_error_handlers));
|
zend_ptr_stack_destroy(&EG(user_error_handlers));
|
||||||
|
|
||||||
|
zend_ptr_stack_clean(&EG(user_exception_handlers), ZVAL_DESTRUCTOR, 1);
|
||||||
|
zend_ptr_stack_destroy(&EG(user_exception_handlers));
|
||||||
|
|
||||||
EG(error_reporting) = EG(orig_error_reporting);
|
EG(error_reporting) = EG(orig_error_reporting);
|
||||||
zend_objects_store_destroy(&EG(objects_store));
|
zend_objects_store_destroy(&EG(objects_store));
|
||||||
} zend_end_try();
|
} zend_end_try();
|
||||||
|
|
|
@ -193,7 +193,9 @@ struct _zend_executor_globals {
|
||||||
int garbage_ptr;
|
int garbage_ptr;
|
||||||
|
|
||||||
zval *user_error_handler;
|
zval *user_error_handler;
|
||||||
|
zval *user_exception_handler;
|
||||||
zend_ptr_stack user_error_handlers;
|
zend_ptr_stack user_error_handlers;
|
||||||
|
zend_ptr_stack user_exception_handlers;
|
||||||
|
|
||||||
/* timeout support */
|
/* timeout support */
|
||||||
int timeout_seconds;
|
int timeout_seconds;
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
|
--TEST--
|
||||||
|
ZE2: set_exception_handler()
|
||||||
|
--SKIPIF--
|
||||||
|
<?php if (version_compare(zend_version(), "2", "<")) print "skip"; ?>
|
||||||
|
--FILE--
|
||||||
|
<?php
|
||||||
|
|
||||||
---- EXPECTED OUTPUT
|
set_exception_handler("my_handler");
|
||||||
test_i
|
try {
|
||||||
test
|
throw new exception();
|
||||||
---- ACTUAL OUTPUT
|
} catch (stdClass $e) {
|
||||||
test_itest
|
print "BAR\n";
|
||||||
---- FAILED
|
}
|
||||||
|
|
||||||
|
function my_handler($exception) {
|
||||||
|
print "FOO\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
--EXPECT--
|
||||||
|
FOO
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue