From a49fa8ce021bc038e296d6f0e4da83736c04c381 Mon Sep 17 00:00:00 2001 From: Stefan Siegl Date: Sat, 12 Apr 2014 00:02:43 +0200 Subject: [PATCH] Unwind V8 execution context on fatal error, refs #87 This is yet a first hack to prove applicability. Currently unwind environment is held in a global variable, i.e. solution is neither thread safe nor reentrant yet. --- php_v8js_macros.h | 2 ++ v8js.cc | 4 ++++ v8js_convert.cc | 44 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 48 insertions(+), 2 deletions(-) diff --git a/php_v8js_macros.h b/php_v8js_macros.h index c43ad8f..1ae9938 100644 --- a/php_v8js_macros.h +++ b/php_v8js_macros.h @@ -205,6 +205,8 @@ struct php_v8js_ctx { std::vector accessor_list; char *tz; + + bool fatal_error_abort; #ifdef ZTS void ***zts_ctx; #endif diff --git a/v8js.cc b/v8js.cc index 5943fd6..a28cd5d 100644 --- a/v8js.cc +++ b/v8js.cc @@ -1134,6 +1134,10 @@ static PHP_METHOD(V8Js, executeString) php_v8js_timer_pop(TSRMLS_C); } + if(c->fatal_error_abort) { + zend_error(E_ERROR, "V8Js caught fatal error; message lost, sorry :-)"); + } + char exception_string[64]; if (c->time_limit_hit) { diff --git a/v8js_convert.cc b/v8js_convert.cc index 227ae2f..db8fa3c 100644 --- a/v8js_convert.cc +++ b/v8js_convert.cc @@ -30,6 +30,17 @@ extern "C" { #include #include + +jmp_buf *unwind_env; + +static void php_v8js_error_handler(int error_num, const char *error_filename, const uint error_lineno, const char *format, va_list args) +{ + longjmp(*unwind_env, 1); +} + + + + static void php_v8js_weak_object_callback(const v8::WeakCallbackData &data); /* Callback for PHP methods and functions */ @@ -43,6 +54,13 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct char *error; int error_len, i, flags = V8JS_FLAG_NONE; +#if PHP_V8_API_VERSION <= 3023008 + /* Until V8 3.23.8 Isolate could only take one external pointer. */ + php_v8js_ctx *ctx = (php_v8js_ctx *) isolate->GetData(); +#else + php_v8js_ctx *ctx = (php_v8js_ctx *) isolate->GetData(0); +#endif + /* Set parameter limits */ min_num_args = method_ptr->common.required_num_args; max_num_args = method_ptr->common.num_args; @@ -125,12 +143,34 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct fcc.called_scope = ce; fcc.object_ptr = value; - /* Call the method */ - zend_call_function(&fci, &fcc TSRMLS_CC); + jmp_buf env; + int val; + + void (*old_error_handler)(int, const char *, const uint, const char*, va_list); + old_error_handler = zend_error_cb; + zend_error_cb = php_v8js_error_handler; + + val = setjmp (env); + unwind_env = &env; + + if (val) { + ctx->fatal_error_abort = true; + zend_error_cb = old_error_handler; + } + else { + /* Call the method */ + zend_call_function(&fci, &fcc TSRMLS_CC); + } } isolate->Enter(); + if(ctx->fatal_error_abort) { + v8::V8::TerminateExecution(isolate); + info.GetReturnValue().Set(V8JS_NULL); + return; + } + failure: /* Cleanup */ if (argc) {