From: Bob Weinand Date: Tue, 12 Jul 2016 18:35:54 +0000 (+0200) Subject: Fix phpdbg ZTS watchpoint+shutdown sequences & opcache+watchpoints X-Git-Tag: php-7.1.0beta1~84 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ef6d0c8b6d0aec0e8a9f02fdd60197db244840a1;p=php Fix phpdbg ZTS watchpoint+shutdown sequences & opcache+watchpoints --- diff --git a/run-tests.php b/run-tests.php index fd4e12081f..0dcf21bcbf 100755 --- a/run-tests.php +++ b/run-tests.php @@ -1366,6 +1366,7 @@ TEST $file return 'SKIPPED'; } } + $uses_cgi = true; } /* For phpdbg tests, check if phpdbg sapi is available and if it is, use it. */ @@ -1916,7 +1917,7 @@ COMMAND $cmd /* when using CGI, strip the headers from the output */ $headers = ""; - if (isset($old_php) && preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $out, $match)) { + if (!empty($uses_cgi) && preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $out, $match)) { $output = trim($match[2]); $rh = preg_split("/[\n\r]+/", $match[1]); $headers = array(); diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 0d0b4b41ca..bf11359bb0 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -77,6 +77,63 @@ static zend_bool phpdbg_booted = 0; static zend_bool phpdbg_fully_started = 0; zend_bool use_mm_wrappers = 0; +static void php_phpdbg_destroy_bp_file(zval *brake) /* {{{ */ +{ + zend_hash_destroy(Z_ARRVAL_P(brake)); + efree(Z_ARRVAL_P(brake)); +} /* }}} */ + +static void php_phpdbg_destroy_bp_symbol(zval *brake) /* {{{ */ +{ + efree((char *) ((phpdbg_breaksymbol_t *) Z_PTR_P(brake))->symbol); + efree(Z_PTR_P(brake)); +} /* }}} */ + +static void php_phpdbg_destroy_bp_opcode(zval *brake) /* {{{ */ +{ + efree((char *) ((phpdbg_breakop_t *) Z_PTR_P(brake))->name); + efree(Z_PTR_P(brake)); +} /* }}} */ + +static void php_phpdbg_destroy_bp_opline(zval *brake) /* {{{ */ +{ + efree(Z_PTR_P(brake)); +} /* }}} */ + +static void php_phpdbg_destroy_bp_methods(zval *brake) /* {{{ */ +{ + zend_hash_destroy(Z_ARRVAL_P(brake)); + efree(Z_ARRVAL_P(brake)); +} /* }}} */ + +static void php_phpdbg_destroy_bp_condition(zval *data) /* {{{ */ +{ + phpdbg_breakcond_t *brake = (phpdbg_breakcond_t *) Z_PTR_P(data); + + if (brake->ops) { + destroy_op_array(brake->ops); + efree(brake->ops); + } + efree((char*) brake->code); + efree(brake); +} /* }}} */ + +static void php_phpdbg_destroy_registered(zval *data) /* {{{ */ +{ + zend_function *function = (zend_function *) Z_PTR_P(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 inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ { pg->prompt[0] = NULL; @@ -124,7 +181,24 @@ static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ { - ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); + 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); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, php_phpdbg_destroy_bp_opline, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], 8, NULL, php_phpdbg_destroy_bp_opcode, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0); + zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], 8, NULL, NULL, 0); + + 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; @@ -143,63 +217,76 @@ static PHP_MINIT_FUNCTION(phpdbg) /* {{{ */ return SUCCESS; } /* }}} */ -static void php_phpdbg_destroy_bp_file(zval *brake) /* {{{ */ +static PHP_MSHUTDOWN_FUNCTION(phpdbg) /* {{{ */ { - zend_hash_destroy(Z_ARRVAL_P(brake)); - efree(Z_ARRVAL_P(brake)); -} /* }}} */ + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]); + zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); + zend_hash_destroy(&PHPDBG_G(file_sources)); + zend_hash_destroy(&PHPDBG_G(seek)); + zend_hash_destroy(&PHPDBG_G(registered)); + phpdbg_destroy_watchpoints(); -static void php_phpdbg_destroy_bp_symbol(zval *brake) /* {{{ */ -{ - efree((char *) ((phpdbg_breaksymbol_t *) Z_PTR_P(brake))->symbol); - efree(Z_PTR_P(brake)); -} /* }}} */ + if (!(PHPDBG_G(flags) & PHPDBG_IS_QUITTING)) { + phpdbg_notice("stop", "type=\"normal\"", "Script ended normally"); + } -static void php_phpdbg_destroy_bp_opcode(zval *brake) /* {{{ */ -{ - efree((char *) ((phpdbg_breakop_t *) Z_PTR_P(brake))->name); - efree(Z_PTR_P(brake)); -} /* }}} */ + /* 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; + } -static void php_phpdbg_destroy_bp_opline(zval *brake) /* {{{ */ -{ - efree(Z_PTR_P(brake)); -} /* }}} */ + if (PHPDBG_G(buffer)) { + free(PHPDBG_G(buffer)); + PHPDBG_G(buffer) = NULL; + } -static void php_phpdbg_destroy_bp_methods(zval *brake) /* {{{ */ -{ - zend_hash_destroy(Z_ARRVAL_P(brake)); - efree(Z_ARRVAL_P(brake)); -} /* }}} */ + if (PHPDBG_G(exec)) { + efree(PHPDBG_G(exec)); + PHPDBG_G(exec) = NULL; + } -static void php_phpdbg_destroy_bp_condition(zval *data) /* {{{ */ -{ - phpdbg_breakcond_t *brake = (phpdbg_breakcond_t *) Z_PTR_P(data); + if (PHPDBG_G(oplog)) { + fclose(PHPDBG_G(oplog)); + PHPDBG_G(oplog) = NULL; + } - if (brake->ops) { - destroy_op_array(brake->ops); - efree(brake->ops); + if (PHPDBG_G(ops)) { + destroy_op_array(PHPDBG_G(ops)); + efree(PHPDBG_G(ops)); + PHPDBG_G(ops) = NULL; } - efree((char*) brake->code); - efree(brake); -} /* }}} */ -static void php_phpdbg_destroy_registered(zval *data) /* {{{ */ -{ - zend_function *function = (zend_function *) Z_PTR_P(data); - destroy_zend_function(function); -} /* }}} */ + if (PHPDBG_G(oplog_list)) { + phpdbg_oplog_list *cur = PHPDBG_G(oplog_list); + do { + phpdbg_oplog_list *prev = cur->prev; + efree(cur); + cur = prev; + } while (cur != NULL); -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); + zend_arena_destroy(PHPDBG_G(oplog_arena)); + PHPDBG_G(oplog_list) = NULL; } - efree(source); -} /* }}} */ + fflush(stdout); + if (SG(request_info).argv0) { + free(SG(request_info).argv0); + SG(request_info).argv0 = NULL; + } + + return SUCCESS; +} +/* }}} */ static PHP_RINIT_FUNCTION(phpdbg) /* {{{ */ { @@ -701,7 +788,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, @@ -796,93 +883,13 @@ static void php_sapi_phpdbg_log_message(char *message, int syslog_type_int) /* { static int php_sapi_phpdbg_activate(void) /* {{{ */ { - 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); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE], 8, NULL, php_phpdbg_destroy_bp_methods, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE], 8, NULL, php_phpdbg_destroy_bp_opline, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE], 8, NULL, php_phpdbg_destroy_bp_opcode, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD], 8, NULL, php_phpdbg_destroy_bp_methods, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_COND], 8, NULL, php_phpdbg_destroy_bp_condition, 0); - zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP], 8, NULL, NULL, 0); - - 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(); - return SUCCESS; } static int php_sapi_phpdbg_deactivate(void) /* {{{ */ { - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_PENDING]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FUNCTION_OPLINE]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD_OPLINE]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_FILE_OPLINE]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPLINE]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_OPCODE]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_METHOD]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_COND]); - zend_hash_destroy(&PHPDBG_G(bp)[PHPDBG_BREAK_MAP]); - zend_hash_destroy(&PHPDBG_G(file_sources)); - zend_hash_destroy(&PHPDBG_G(seek)); - zend_hash_destroy(&PHPDBG_G(registered)); - phpdbg_destroy_watchpoints(); - - /* 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)); - PHPDBG_G(buffer) = NULL; - } - - if (PHPDBG_G(exec)) { - efree(PHPDBG_G(exec)); - PHPDBG_G(exec) = NULL; - } - - if (PHPDBG_G(oplog)) { - fclose(PHPDBG_G(oplog)); - PHPDBG_G(oplog) = NULL; - } - - if (PHPDBG_G(ops)) { - destroy_op_array(PHPDBG_G(ops)); - efree(PHPDBG_G(ops)); - PHPDBG_G(ops) = NULL; - } - - if (PHPDBG_G(oplog_list)) { - phpdbg_oplog_list *cur = PHPDBG_G(oplog_list); - do { - phpdbg_oplog_list *prev = cur->prev; - efree(cur); - cur = prev; - } while (cur != NULL); - - zend_arena_destroy(PHPDBG_G(oplog_arena)); - 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 void php_sapi_phpdbg_register_vars(zval *track_vars_array) /* {{{ */ { @@ -1358,6 +1365,7 @@ 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); @@ -1366,7 +1374,6 @@ int main(int argc, char **argv) /* {{{ */ zend_signal_startup(); -phpdbg_main: ini_entries = NULL; ini_entries_len = 0; ini_ignore = 0; @@ -1446,9 +1453,6 @@ phpdbg_main: /* begin phpdbg options */ case 'S': { /* set SAPI name */ - if (sapi_name) { - free(sapi_name); - } sapi_name = strdup(php_optarg); } break; @@ -1523,6 +1527,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; @@ -1538,6 +1543,7 @@ phpdbg_main: } break; case 'V': { + ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); sapi_startup(phpdbg); phpdbg->startup(phpdbg); printf( @@ -1614,6 +1620,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 @@ -1624,18 +1644,6 @@ 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); - } - /* setup remote server if necessary */ if (cleaning <= 0 && listen > 0) { server = phpdbg_open_socket(address, listen); @@ -2008,28 +2016,47 @@ phpdbg_out: 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 + 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(); - sapi_shutdown(); +#ifdef ZTS + ts_free_id(phpdbg_globals_id); +#endif + + if (sapi_name) { + free(sapi_name); } + zend_signal_shutdown(); + +#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); @@ -2037,21 +2064,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; } /* }}} */ diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index e01e9a787d..63af56793b 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -939,7 +939,7 @@ zend_string *phpdbg_watchpoint_change_collision_name(phpdbg_watchpoint_t *watch) } ZEND_HASH_FOREACH_PTR(&watch->elements, element) { if (element->flags & PHPDBG_WATCH_IMPLICIT) { - if ((watch->type == WATCH_ON_ZVAL || watch->type == WATCH_ON_BUCKET) && Z_REFCOUNTED(watch->backup.zv)) { + if ((watch->type == WATCH_ON_ZVAL || watch->type == WATCH_ON_BUCKET) && Z_TYPE(watch->backup.zv) > IS_STRING) { phpdbg_update_watch_element_watch(element->child); } continue;