diff options
Diffstat (limited to 'sapi/phpdbg/phpdbg.c')
-rw-r--r-- | sapi/phpdbg/phpdbg.c | 325 |
1 files changed, 171 insertions, 154 deletions
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 9b7993ddf0..1e0b214a23 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -18,10 +18,6 @@ +----------------------------------------------------------------------+ */ -#if !defined(ZEND_SIGNALS) || defined(_WIN32) -# include <signal.h> -#endif - #include "phpdbg.h" #include "phpdbg_prompt.h" #include "phpdbg_bp.h" @@ -75,72 +71,7 @@ PHP_INI_END() static zend_bool phpdbg_booted = 0; static zend_bool phpdbg_fully_started = 0; - -static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ -{ - pg->prompt[0] = NULL; - pg->prompt[1] = NULL; - - pg->colors[0] = NULL; - pg->colors[1] = NULL; - pg->colors[2] = NULL; - - pg->lines = phpdbg_get_terminal_height(); - pg->exec = NULL; - pg->exec_len = 0; - pg->buffer = NULL; - pg->last_was_newline = 1; - pg->ops = NULL; - pg->vmret = 0; - pg->in_execution = 0; - pg->bp_count = 0; - pg->flags = PHPDBG_DEFAULT_FLAGS; - pg->oplog = NULL; - memset(pg->io, 0, sizeof(pg->io)); - pg->frame.num = 0; - pg->sapi_name_ptr = NULL; - pg->socket_fd = -1; - pg->socket_server_fd = -1; - pg->unclean_eval = 0; - - pg->req_id = 0; - pg->err_buf.active = 0; - pg->err_buf.type = 0; - - pg->input_buflen = 0; - pg->sigsafe_mem.mem = NULL; - pg->sigsegv_bailout = NULL; - - pg->oplog_list = NULL; - -#ifdef PHP_WIN32 - pg->sigio_watcher_thread = INVALID_HANDLE_VALUE; - memset(&pg->swd, 0, sizeof(struct win32_sigio_watcher_data)); -#endif - - pg->eol = PHPDBG_EOL_LF; -} /* }}} */ - -static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ -{ - ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); - REGISTER_INI_ENTRIES(); - - zend_execute_ex = phpdbg_execute_ex; - - REGISTER_STRINGL_CONSTANT("PHPDBG_VERSION", PHPDBG_VERSION, sizeof(PHPDBG_VERSION)-1, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PHPDBG_FILE", FILE_PARAM, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PHPDBG_METHOD", METHOD_PARAM, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PHPDBG_LINENO", NUMERIC_PARAM, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PHPDBG_FUNC", STR_PARAM, CONST_CS|CONST_PERSISTENT); - - REGISTER_LONG_CONSTANT("PHPDBG_COLOR_PROMPT", PHPDBG_COLOR_PROMPT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PHPDBG_COLOR_NOTICE", PHPDBG_COLOR_NOTICE, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("PHPDBG_COLOR_ERROR", PHPDBG_COLOR_ERROR, CONST_CS|CONST_PERSISTENT); - - return SUCCESS; -} /* }}} */ +zend_bool use_mm_wrappers = 0; static void php_phpdbg_destroy_bp_file(zval *brake) /* {{{ */ { @@ -189,8 +120,62 @@ static void php_phpdbg_destroy_registered(zval *data) /* {{{ */ destroy_zend_function(function); } /* }}} */ +static void php_phpdbg_destroy_file_source(zval *data) /* {{{ */ +{ + phpdbg_file_source *source = (phpdbg_file_source *) Z_PTR_P(data); + destroy_op_array(&source->op_array); + if (source->buf) { + efree(source->buf); + } + efree(source); +} /* }}} */ -static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ +static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ +{ + pg->prompt[0] = NULL; + pg->prompt[1] = NULL; + + pg->colors[0] = NULL; + pg->colors[1] = NULL; + pg->colors[2] = NULL; + + pg->lines = phpdbg_get_terminal_height(); + pg->exec = NULL; + pg->exec_len = 0; + pg->buffer = NULL; + pg->last_was_newline = 1; + pg->ops = NULL; + pg->vmret = 0; + pg->in_execution = 0; + pg->bp_count = 0; + pg->flags = PHPDBG_DEFAULT_FLAGS; + pg->oplog = NULL; + memset(pg->io, 0, sizeof(pg->io)); + pg->frame.num = 0; + pg->sapi_name_ptr = NULL; + pg->socket_fd = -1; + pg->socket_server_fd = -1; + pg->unclean_eval = 0; + + pg->req_id = 0; + pg->err_buf.active = 0; + pg->err_buf.type = 0; + + pg->input_buflen = 0; + pg->sigsafe_mem.mem = NULL; + pg->sigsegv_bailout = NULL; + + pg->oplog_list = NULL; + +#ifdef PHP_WIN32 + pg->sigio_watcher_thread = INVALID_HANDLE_VALUE; + memset(&pg->swd, 0, sizeof(struct win32_sigio_watcher_data)); +#endif + + pg->eol = PHPDBG_EOL_LF; +} /* }}} */ + +static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ { zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE], 8, NULL, php_phpdbg_destroy_bp_file, 0); zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING], 8, NULL, php_phpdbg_destroy_bp_file, 0); @@ -207,10 +192,28 @@ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ zend_hash_init(&PHPDBG_G(seek), 8, NULL, NULL, 0); zend_hash_init(&PHPDBG_G(registered), 8, NULL, php_phpdbg_destroy_registered, 0); + zend_hash_init(&PHPDBG_G(file_sources), 0, NULL, php_phpdbg_destroy_file_source, 0); + phpdbg_setup_watchpoints(); + + REGISTER_INI_ENTRIES(); + + zend_execute_ex = phpdbg_execute_ex; + + REGISTER_STRINGL_CONSTANT("PHPDBG_VERSION", PHPDBG_VERSION, sizeof(PHPDBG_VERSION)-1, CONST_CS|CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("PHPDBG_FILE", FILE_PARAM, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHPDBG_METHOD", METHOD_PARAM, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHPDBG_LINENO", NUMERIC_PARAM, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHPDBG_FUNC", STR_PARAM, CONST_CS|CONST_PERSISTENT); + + REGISTER_LONG_CONSTANT("PHPDBG_COLOR_PROMPT", PHPDBG_COLOR_PROMPT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHPDBG_COLOR_NOTICE", PHPDBG_COLOR_NOTICE, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("PHPDBG_COLOR_ERROR", PHPDBG_COLOR_ERROR, CONST_CS|CONST_PERSISTENT); + return SUCCESS; } /* }}} */ -static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ +static PHP_MSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ { zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); @@ -226,8 +229,17 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ zend_hash_destroy(&PHPDBG_G(file_sources)); zend_hash_destroy(&PHPDBG_G(seek)); zend_hash_destroy(&PHPDBG_G(registered)); - zend_hash_destroy(&PHPDBG_G(watchpoints)); - zend_llist_destroy(&PHPDBG_G(watchlist_mem)); + phpdbg_destroy_watchpoints(); + + if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + } + + /* hack to restore mm_heap->use_custom_heap in order to receive memory leak info */ + if (use_mm_wrappers) { + /* ASSUMING that mm_heap->use_custom_heap is the first element of the struct ... */ + *(int *) zend_mm_get_heap() = 0; + } if (PHPDBG_G(buffer)) { free(PHPDBG_G(buffer)); @@ -262,6 +274,26 @@ static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ PHPDBG_G(oplog_list) = NULL; } + fflush(stdout); + if (SG(request_info).argv0) { + free(SG(request_info).argv0); + SG(request_info).argv0 = NULL; + } + + return SUCCESS; +} +/* }}} */ + +static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ +{ + /* deactivate symbol table caching to have these properly destroyed upon stack leaving (especially important for watchpoints) */ + EG(symtable_cache_limit) = EG(symtable_cache) - 1; + + return SUCCESS; +} /* }}} */ + +static PHP_RSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ +{ return SUCCESS; } /* }}} */ @@ -752,7 +784,7 @@ static zend_module_entry sapi_phpdbg_module_entry = { PHPDBG_NAME, phpdbg_user_functions, PHP_MINIT(phpdbg), - NULL, + PHP_MSHUTDOWN(phpdbg), PHP_RINIT(phpdbg), PHP_RSHUTDOWN(phpdbg), NULL, @@ -795,7 +827,7 @@ static void php_sapi_phpdbg_send_header(sapi_header_struct *sapi_header, void *s } /* }}} */ -static void php_sapi_phpdbg_log_message(char *message) /* {{{ */ +static void php_sapi_phpdbg_log_message(char *message, int syslog_type_int) /* {{{ */ { /* * We must not request TSRM before being booted @@ -845,17 +877,15 @@ static void php_sapi_phpdbg_log_message(char *message) /* {{{ */ } /* }}} */ -static int php_sapi_phpdbg_deactivate(void) /* {{{ */ +static int php_sapi_phpdbg_activate(void) /* {{{ */ { - fflush(stdout); - if (SG(request_info).argv0) { - free(SG(request_info).argv0); - SG(request_info).argv0 = NULL; - } + return SUCCESS; +} +static int php_sapi_phpdbg_deactivate(void) /* {{{ */ +{ return SUCCESS; } -/* }}} */ static void php_sapi_phpdbg_register_vars(zval *track_vars_array) /* {{{ */ { @@ -994,7 +1024,7 @@ static sapi_module_struct phpdbg_sapi_module = { php_sapi_phpdbg_module_startup, /* startup */ php_module_shutdown_wrapper, /* shutdown */ - NULL, /* activate */ + php_sapi_phpdbg_activate, /* activate */ php_sapi_phpdbg_deactivate, /* deactivate */ php_sapi_phpdbg_ub_write, /* unbuffered write */ @@ -1236,16 +1266,12 @@ void phpdbg_signal_handler(int sig, siginfo_t *info, void *context) /* {{{ */ switch (sig) { case SIGBUS: case SIGSEGV: - if (PHPDBG_G(sigsegv_bailout)) { - LONGJMP(*PHPDBG_G(sigsegv_bailout), FAILURE); - } is_handled = phpdbg_watchpoint_segfault_handler(info, context); if (is_handled == FAILURE) { -#ifdef ZEND_SIGNALS + if (PHPDBG_G(sigsegv_bailout)) { + LONGJMP(*PHPDBG_G(sigsegv_bailout), FAILURE); + } zend_sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL); -#else - sigaction(sig, &PHPDBG_G(old_sigsegv_signal), NULL); -#endif } break; } @@ -1312,7 +1338,6 @@ int main(int argc, char **argv) /* {{{ */ FILE* stream = NULL; char *print_opline_func; zend_bool ext_stmt = 0; - zend_bool use_mm_wrappers = 0; zend_bool is_exit; int exit_status; @@ -1336,17 +1361,15 @@ int main(int argc, char **argv) /* {{{ */ setmode(_fileno(stderr), O_BINARY); /* make the stdio mode be binary */ #endif +phpdbg_main: #ifdef ZTS tsrm_startup(1, 1, 0, NULL); (void)ts_resource(0); ZEND_TSRMLS_CACHE_UPDATE(); #endif -#ifdef ZEND_SIGNALS zend_signal_startup(); -#endif -phpdbg_main: ini_entries = NULL; ini_entries_len = 0; ini_ignore = 0; @@ -1426,9 +1449,6 @@ phpdbg_main: /* begin phpdbg options */ case 'S': { /* set SAPI name */ - if (sapi_name) { - free(sapi_name); - } sapi_name = strdup(php_optarg); } break; @@ -1503,6 +1523,7 @@ phpdbg_main: } break; case 'h': { + ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); sapi_startup(phpdbg); phpdbg->startup(phpdbg); PHPDBG_G(flags) = 0; @@ -1518,6 +1539,7 @@ phpdbg_main: } break; case 'V': { + ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); sapi_startup(phpdbg); phpdbg->startup(phpdbg); printf( @@ -1594,6 +1616,20 @@ phpdbg_main: phpdbg->ini_entries = ini_entries; + ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); + + if (settings > (zend_phpdbg_globals *) 0x2) { +#ifdef ZTS + *((zend_phpdbg_globals *) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(phpdbg_globals_id)]) = *settings; +#else + phpdbg_globals = *settings; +#endif + free(settings); + } + + /* set flags from command line */ + PHPDBG_G(flags) = flags; + if (phpdbg->startup(phpdbg) == SUCCESS) { zend_mm_heap *mm_heap; #ifdef _WIN32 @@ -1604,17 +1640,9 @@ phpdbg_main: void (*_free)(void*); void* (*_realloc)(void*, size_t); - /* set flags from command line */ - PHPDBG_G(flags) = flags; - - if (settings > (zend_phpdbg_globals *) 0x2) { -#ifdef ZTS - *((zend_phpdbg_globals *) (*((void ***) TSRMLS_CACHE))[TSRM_UNSHUFFLE_RSRC_ID(phpdbg_globals_id)]) = *settings; -#else - phpdbg_globals = *settings; -#endif - free(settings); - } + zend_try { + zend_signal_activate(); + } zend_end_try(); /* setup remote server if necessary */ if (cleaning <= 0 && listen > 0) { @@ -1624,7 +1652,7 @@ phpdbg_main: } #ifndef _WIN32 - sigaction(SIGIO, &sigio_struct, NULL); + zend_sigaction(SIGIO, &sigio_struct, NULL); #endif /* set remote flag to stop service shutting down upon quit */ @@ -1632,7 +1660,7 @@ phpdbg_main: #ifndef _WIN32 } else { - signal(SIGHUP, phpdbg_sighup_handler); + zend_signal(SIGHUP, phpdbg_sighup_handler); #endif } @@ -1641,8 +1669,6 @@ phpdbg_main: use_mm_wrappers = !_malloc && !_realloc && !_free; - phpdbg_init_list(); - PHPDBG_G(original_free_function) = _free; _free = phpdbg_watch_efree; @@ -1656,21 +1682,8 @@ phpdbg_main: zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc); } - phpdbg_setup_watchpoints(); -#if defined(ZEND_SIGNALS) && !defined(_WIN32) - zend_try { - zend_signal_activate(); - } zend_end_try(); -#endif - -#if defined(ZEND_SIGNALS) && !defined(_WIN32) - zend_try { zend_sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); } zend_end_try(); - zend_try { zend_sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); } zend_end_try(); -#elif !defined(_WIN32) - sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); - sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); -#endif + phpdbg_init_list(); PHPDBG_G(sapi_name_ptr) = sapi_name; @@ -1708,24 +1721,24 @@ phpdbg_main: return 1; } +#ifndef _WIN32 + zend_try { zend_sigaction(SIGSEGV, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); } zend_end_try(); + zend_try { zend_sigaction(SIGBUS, &signal_struct, &PHPDBG_G(old_sigsegv_signal)); } zend_end_try(); +#endif + /* do not install sigint handlers for remote consoles */ /* sending SIGINT then provides a decent way of shutting down the server */ #ifndef _WIN32 if (listen < 0) { #endif -#if defined(ZEND_SIGNALS) && !defined(_WIN32) zend_try { zend_signal(SIGINT, phpdbg_sigint_handler); } zend_end_try(); -#else - signal(SIGINT, phpdbg_sigint_handler); -#endif #ifndef _WIN32 } /* setup io here */ if (remote) { PHPDBG_G(flags) |= PHPDBG_IS_REMOTE; - - signal(SIGPIPE, SIG_IGN); + zend_signal(SIGPIPE, SIG_IGN); } PHPDBG_G(io)[PHPDBG_STDIN].ptr = stdin; PHPDBG_G(io)[PHPDBG_STDIN].fd = fileno(stdin); @@ -1955,6 +1968,10 @@ phpdbg_out: zend_objects_store_mark_destructed(&EG(objects_store)); } + zend_try { + php_request_shutdown(NULL); + } zend_end_try(); + /* backup globals when cleaning */ if ((cleaning > 0 || remote) && !quit_immediately) { settings = calloc(1, sizeof(zend_phpdbg_globals)); @@ -1982,41 +1999,50 @@ phpdbg_out: } } - /* hack to restore mm_heap->use_custom_heap in order to receive memory leak info */ - if (use_mm_wrappers) { - /* ASSUMING that mm_heap->use_custom_heap is the first element of the struct ... */ - *(int *) mm_heap = 0; - } - zend_try { - php_request_shutdown(NULL); - } zend_end_try(); - if (exit_status == 0) { exit_status = EG(exit_status); } + php_output_deactivate(); + if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + PHPDBG_G(flags) |= PHPDBG_IS_QUITTING; if (PHPDBG_G(in_execution) || is_exit) { if (!quit_immediately && !phpdbg_startup_run) { - phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + PHPDBG_G(flags) -= PHPDBG_IS_QUITTING; cleaning++; } } } - php_output_deactivate(); zend_try { php_module_shutdown(); } zend_end_try(); #ifndef _WIN32 + /* force override (no zend_signals) to prevent crashes due to signal recursion in SIGSEGV/SIGBUS handlers */ + signal(SIGSEGV, SIG_DFL); + signal(SIGBUS, SIG_DFL); + /* reset it... else we risk a stack overflow upon next run (when clean'ing) */ php_stream_stdio_ops.write = PHPDBG_G(php_stdiop_write); #endif + } + + sapi_shutdown(); + +#ifdef ZTS + ts_free_id(phpdbg_globals_id); +#endif - sapi_shutdown(); + if (sapi_name) { + free(sapi_name); } +#ifdef ZTS + tsrm_shutdown(); +#endif + if ((cleaning > 0 || remote) && !quit_immediately) { /* reset internal php_getopt state */ php_getopt(-1, argv, OPTIONS, NULL, &php_optind, 0, 0); @@ -2024,21 +2050,12 @@ phpdbg_out: goto phpdbg_main; } -#ifdef ZTS - /* bugggy */ - /* tsrm_shutdown(); */ -#endif - #ifndef _WIN32 if (address) { free(address); } #endif - if (PHPDBG_G(sapi_name_ptr)) { - free(PHPDBG_G(sapi_name_ptr)); - } - /* usually 0; just for -rr */ return exit_status; } /* }}} */ |