diff options
Diffstat (limited to 'sapi/phpdbg/phpdbg.c')
| -rw-r--r-- | sapi/phpdbg/phpdbg.c | 360 | 
1 files changed, 193 insertions, 167 deletions
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index d2de0c2e30..f570763ca0 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,6 +71,65 @@ PHP_INI_END()  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->filename); +	efree(source); +} /* }}} */  static inline void php_phpdbg_globals_ctor(zend_phpdbg_globals *pg) /* {{{ */  { @@ -127,75 +182,6 @@ 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); -	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 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 PHP_RINIT_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);  	zend_hash_init(&PHPDBG_G(bp)[PHPDBG_BREAK_SYM], 8, NULL, php_phpdbg_destroy_bp_symbol, 0); @@ -211,10 +197,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]); @@ -230,8 +234,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)); @@ -266,6 +279,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) /* {{{ */ +{  	if (PHPDBG_G(stdin_file)) {  		fclose(PHPDBG_G(stdin_file));  		PHPDBG_G(stdin_file) = NULL; @@ -771,7 +804,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, @@ -779,13 +812,17 @@ static zend_module_entry sapi_phpdbg_module_entry = {  	STANDARD_MODULE_PROPERTIES  }; +static void phpdbg_interned_strings_nothing(void) { } +  static inline int php_sapi_phpdbg_module_startup(sapi_module_struct *module) /* {{{ */  {  	if (php_module_startup(module, &sapi_phpdbg_module_entry, 1) == FAILURE) {  		return FAILURE;  	} +	/* prevent zend_interned_strings_restore from invalidating our string pointers too early (in phpdbg allocated memory only gets freed after module shutdown) */ +	zend_interned_strings_restore = phpdbg_interned_strings_nothing; -	phpdbg_booted=1; +	phpdbg_booted = 1;  	return SUCCESS;  } /* }}} */ @@ -814,7 +851,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 @@ -864,17 +901,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) /* {{{ */  { @@ -1016,7 +1051,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 */ @@ -1263,16 +1298,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;  	} @@ -1361,12 +1392,15 @@ 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;  	char *read_from_stdin = NULL;  	zend_string *backup_phpdbg_compile = NULL;  	zend_bool show_help = 0, show_version = 0; +	void* (*_malloc)(size_t); +	void (*_free)(void*); +	void* (*_realloc)(void*, size_t); +  #ifndef _WIN32  	struct sigaction sigio_struct; @@ -1388,17 +1422,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; @@ -1484,9 +1516,6 @@ phpdbg_main:  			} break;  			case 'S': { /* set SAPI name */ -				if (sapi_name) { -					free(sapi_name); -				}  				sapi_name = strdup(php_optarg);  			} break; @@ -1631,26 +1660,34 @@ phpdbg_main:  	phpdbg->ini_entries = ini_entries; +	ZEND_INIT_MODULE_GLOBALS(phpdbg, php_phpdbg_globals_ctor, NULL); + +	/* set default colors */ +	phpdbg_set_color_ex(PHPDBG_COLOR_PROMPT,  PHPDBG_STRL("white-bold")); +	phpdbg_set_color_ex(PHPDBG_COLOR_ERROR,   PHPDBG_STRL("red-bold")); +	phpdbg_set_color_ex(PHPDBG_COLOR_NOTICE,  PHPDBG_STRL("green")); + +	/* set default prompt */ +	phpdbg_set_prompt(PHPDBG_DEFAULT_PROMPT); + +	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      EXCEPTION_POINTERS *xp;      __try {  #endif -		void* (*_malloc)(size_t); -		void (*_free)(void*); -		void* (*_realloc)(void*, size_t); - -		/* set flags from command line */ -		PHPDBG_G(flags) = flags; - -		/* set default colors */ -		phpdbg_set_color_ex(PHPDBG_COLOR_PROMPT,  PHPDBG_STRL("white-bold")); -		phpdbg_set_color_ex(PHPDBG_COLOR_ERROR,   PHPDBG_STRL("red-bold")); -		phpdbg_set_color_ex(PHPDBG_COLOR_NOTICE,  PHPDBG_STRL("green")); - -		/* set default prompt */ -		phpdbg_set_prompt(PHPDBG_DEFAULT_PROMPT);  		if (show_version || show_help) {  			/* It ain't gonna proceed to real execution anyway, @@ -1689,14 +1726,9 @@ phpdbg_main:  			goto free_and_return;  		} -		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) { @@ -1706,7 +1738,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 */ @@ -1714,7 +1746,7 @@ phpdbg_main:  #ifndef _WIN32  		} else { -			signal(SIGHUP, phpdbg_sighup_handler); +			zend_signal(SIGHUP, phpdbg_sighup_handler);  #endif  		} @@ -1723,8 +1755,6 @@ phpdbg_main:  		use_mm_wrappers = !_malloc && !_realloc && !_free; -		phpdbg_init_list(); -  		PHPDBG_G(original_free_function) = _free;  		_free = phpdbg_watch_efree; @@ -1738,21 +1768,10 @@ phpdbg_main:  			zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc);  		} -		phpdbg_setup_watchpoints(); +		_free = PHPDBG_G(original_free_function); -#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; @@ -1790,24 +1809,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); @@ -2073,6 +2092,10 @@ phpdbg_out:  			zend_objects_store_mark_destructed(&EG(objects_store));  		} +		zend_try { +			php_request_shutdown(NULL); +		} zend_end_try(); +  		if (PHPDBG_G(exec) && !memcmp("-", PHPDBG_G(exec), 2)) { /* i.e. execution context has been read from stdin - back it up */  			phpdbg_file_source *data = zend_hash_str_find_ptr(&PHPDBG_G(file_sources), PHPDBG_G(exec), PHPDBG_G(exec_len));  			backup_phpdbg_compile = zend_string_alloc(data->len + 2, 1); @@ -2110,28 +2133,21 @@ 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();  		{  			php_stream_wrapper *wrapper = zend_hash_str_find_ptr(php_stream_get_url_stream_wrappers_hash(), ZEND_STRL("php")); @@ -2143,11 +2159,19 @@ phpdbg_out:  		} 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(); +	sapi_shutdown(); + +	if (sapi_name) { +		free(sapi_name);  	}  free_and_return: @@ -2156,6 +2180,17 @@ free_and_return:  		read_from_stdin = NULL;  	} +#ifdef ZTS +	/* reset to original handlers - otherwise PHPDBG_G() in phpdbg_watch_efree will be segfaulty (with e.g. USE_ZEND_ALLOC=0) */ +	if (!use_mm_wrappers) { +		zend_mm_set_custom_handlers(zend_mm_get_heap(), _malloc, _free, _realloc); +	} + +	ts_free_id(phpdbg_globals_id); + +	tsrm_shutdown(); +#endif +  	if ((cleaning > 0 || remote) && !quit_immediately) {  		/* reset internal php_getopt state */  		php_getopt(-1, argv, OPTIONS, NULL, &php_optind, 0, 0); @@ -2163,11 +2198,6 @@ free_and_return:  		goto phpdbg_main;  	} -#ifdef ZTS -	/* bugggy */ -	/* tsrm_shutdown(); */ -#endif -  	if (backup_phpdbg_compile) {  		zend_string_free(backup_phpdbg_compile);  	} @@ -2178,10 +2208,6 @@ free_and_return:  	}  #endif -	if (PHPDBG_G(sapi_name_ptr)) { -		free(PHPDBG_G(sapi_name_ptr)); -	} -  	/* usually 0; just for -rr */  	return exit_status;  } /* }}} */  | 
