summaryrefslogtreecommitdiff
path: root/sapi/phpdbg/phpdbg_prompt.c
diff options
context:
space:
mode:
Diffstat (limited to 'sapi/phpdbg/phpdbg_prompt.c')
-rw-r--r--sapi/phpdbg/phpdbg_prompt.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index ac3fb67dbd..11af5bc790 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -24,6 +24,7 @@
#include "zend_compile.h"
#include "zend_exceptions.h"
#include "zend_vm.h"
+#include "zend_generators.h"
#include "phpdbg.h"
#include "phpdbg_help.h"
@@ -647,6 +648,7 @@ PHPDBG_COMMAND(run) /* {{{ */
} else {
zend_rebuild_symbol_table();
}
+ PHPDBG_G(handled_exception) = NULL;
/* clean seek state */
PHPDBG_G(flags) &= ~PHPDBG_SEEK_MASK;
@@ -1376,7 +1378,12 @@ void phpdbg_clean(zend_bool full) /* {{{ */
}
} /* }}} */
+/* code may behave weirdly if EG(exception) is set */
#define DO_INTERACTIVE(allow_async_unsafe) do { \
+ if (exception) { \
+ ++GC_REFCOUNT(exception); \
+ zend_clear_exception(); \
+ } \
if (!(PHPDBG_G(flags) & PHPDBG_IN_EVAL)) { \
const char *file_char = zend_get_executed_filename(); \
zend_string *file = zend_string_init(file_char, strlen(file_char), 0); \
@@ -1385,6 +1392,13 @@ void phpdbg_clean(zend_bool full) /* {{{ */
} \
\
switch (phpdbg_interactive(allow_async_unsafe)) { \
+ zval zv; \
+ default: \
+ if (exception) { \
+ Z_OBJ(zv) = exception; \
+ zend_throw_exception_internal(&zv); \
+ } \
+ /* fallthrough */ \
case PHPDBG_LEAVE: \
case PHPDBG_FINISH: \
case PHPDBG_UNTIL: \
@@ -1408,6 +1422,8 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */
PHPDBG_G(in_execution) = 1;
while (1) {
+ zend_object *exception = EG(exception);
+
if ((PHPDBG_G(flags) & PHPDBG_BP_RESOLVE_MASK)) {
/* resolve nth opline breakpoints */
phpdbg_resolve_op_array_breaks(&execute_data->func->op_array);
@@ -1419,6 +1435,28 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */
}
#endif
+ /* check for uncaught exceptions */
+ if (exception && PHPDBG_G(handled_exception) != exception) {
+ zend_execute_data *prev_ex = execute_data;
+
+ do {
+ prev_ex = zend_generator_check_placeholder_frame(prev_ex);
+ /* assuming that no internal functions will silently swallow exceptions ... */
+ if (!prev_ex->func || !ZEND_USER_CODE(prev_ex->func->common.type)) {
+ continue;
+ }
+
+ if (phpdbg_check_caught_ex(prev_ex)) {
+ goto ex_is_caught;
+ }
+ } while ((prev_ex = prev_ex->prev_execute_data));
+
+ PHPDBG_G(handled_exception) = EG(exception);
+ phpdbg_error("exception", "name=\"%s\"", "Uncaught exception %s", exception->ce->name->val);
+ DO_INTERACTIVE(1);
+ }
+ex_is_caught:
+
/* allow conditional breakpoints and
initialization to access the vm uninterrupted */
if ((PHPDBG_G(flags) & PHPDBG_IN_COND_BP) ||
@@ -1540,6 +1578,7 @@ next:
/* only if *not* interactive and while executing */
void phpdbg_force_interruption(void) /* {{{ */ {
+ zend_object *exception = EG(exception);
zend_execute_data *data = EG(current_execute_data); /* should be always readable if not NULL */
PHPDBG_G(flags) |= PHPDBG_IN_SIGNAL_HANDLER;
@@ -1581,4 +1620,3 @@ PHPDBG_COMMAND(eol) /* {{{ */
return SUCCESS;
} /* }}} */
-