mirror of
https://github.com/phpv8/v8js.git
synced 2024-11-09 16:28:41 +00:00
Use zend_try/zend_catch to unwind v8 stack
This commit is contained in:
parent
dbea6fc122
commit
a2a9c30a11
@ -227,12 +227,7 @@ ZEND_BEGIN_MODULE_GLOBALS(v8js)
|
|||||||
std::mutex timer_mutex;
|
std::mutex timer_mutex;
|
||||||
bool timer_stop;
|
bool timer_stop;
|
||||||
|
|
||||||
// fatal error unwinding
|
|
||||||
bool fatal_error_abort;
|
bool fatal_error_abort;
|
||||||
int error_num;
|
|
||||||
char *error_message;
|
|
||||||
jmp_buf *unwind_env;
|
|
||||||
void (*old_error_handler)(int, const char *, const uint, const char*, va_list);
|
|
||||||
ZEND_END_MODULE_GLOBALS(v8js)
|
ZEND_END_MODULE_GLOBALS(v8js)
|
||||||
|
|
||||||
extern zend_v8js_globals v8js_globals;
|
extern zend_v8js_globals v8js_globals;
|
||||||
|
9
v8js.cc
9
v8js.cc
@ -1263,10 +1263,7 @@ static void php_v8js_call_v8(php_v8js_ctx *c, zval **return_value,
|
|||||||
/* Check for fatal error marker possibly set by php_v8js_error_handler; just
|
/* Check for fatal error marker possibly set by php_v8js_error_handler; just
|
||||||
* rethrow the error since we're now out of V8. */
|
* rethrow the error since we're now out of V8. */
|
||||||
if(V8JSG(fatal_error_abort)) {
|
if(V8JSG(fatal_error_abort)) {
|
||||||
V8JSG(fatal_error_abort) = 0;
|
zend_bailout();
|
||||||
V8JSG(unwind_env) = NULL;
|
|
||||||
|
|
||||||
zend_error(V8JSG(error_num), "%s", V8JSG(error_message));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char exception_string[64];
|
char exception_string[64];
|
||||||
@ -2246,10 +2243,6 @@ static PHP_GINIT_FUNCTION(v8js)
|
|||||||
new(&v8js_globals->timer_stack) std::deque<php_v8js_timer_ctx *>;
|
new(&v8js_globals->timer_stack) std::deque<php_v8js_timer_ctx *>;
|
||||||
|
|
||||||
v8js_globals->fatal_error_abort = 0;
|
v8js_globals->fatal_error_abort = 0;
|
||||||
v8js_globals->error_num = 0;
|
|
||||||
v8js_globals->error_message = 0;
|
|
||||||
v8js_globals->unwind_env = NULL;
|
|
||||||
v8js_globals->old_error_handler = NULL;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
104
v8js_convert.cc
104
v8js_convert.cc
@ -29,41 +29,7 @@ extern "C" {
|
|||||||
#include <v8.h>
|
#include <v8.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
/* Callback for PHP's zend_error_cb; catching any fatal PHP error.
|
|
||||||
* The callback is installed in the lowest (stack wise) php_v8js_call_php_func
|
|
||||||
* frame. Just store the error message and jump right back there and fall
|
|
||||||
* back into V8 context. */
|
|
||||||
static void php_v8js_error_handler(int error_num, const char *error_filename,
|
|
||||||
const uint error_lineno, const char *format,
|
|
||||||
va_list args) /* {{{ */
|
|
||||||
{
|
|
||||||
char *buffer;
|
|
||||||
int buffer_len;
|
|
||||||
|
|
||||||
TSRMLS_FETCH();
|
|
||||||
|
|
||||||
switch (error_num)
|
|
||||||
{
|
|
||||||
case E_ERROR:
|
|
||||||
case E_CORE_ERROR:
|
|
||||||
case E_USER_ERROR:
|
|
||||||
buffer_len = vspprintf(&buffer, PG(log_errors_max_len), format, args);
|
|
||||||
|
|
||||||
V8JSG(fatal_error_abort) = true;
|
|
||||||
V8JSG(error_num) = error_num;
|
|
||||||
V8JSG(error_message) = buffer;
|
|
||||||
|
|
||||||
longjmp(*V8JSG(unwind_env), 1);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
V8JSG(old_error_handler)(error_num, error_filename, error_lineno, format, args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* }}} */
|
|
||||||
|
|
||||||
|
|
||||||
static void php_v8js_weak_object_callback(const v8::WeakCallbackData<v8::Object, zval> &data);
|
static void php_v8js_weak_object_callback(const v8::WeakCallbackData<v8::Object, zval> &data);
|
||||||
|
|
||||||
@ -153,64 +119,28 @@ static void php_v8js_call_php_func(zval *value, zend_class_entry *ce, zend_funct
|
|||||||
fci.no_separation = 1;
|
fci.no_separation = 1;
|
||||||
info.GetReturnValue().Set(V8JS_NULL);
|
info.GetReturnValue().Set(V8JS_NULL);
|
||||||
|
|
||||||
{
|
zend_try {
|
||||||
isolate->Exit();
|
{
|
||||||
v8::Unlocker unlocker(isolate);
|
isolate->Exit();
|
||||||
|
v8::Unlocker unlocker(isolate);
|
||||||
|
|
||||||
/* zend_fcall_info_cache */
|
/* zend_fcall_info_cache */
|
||||||
fcc.initialized = 1;
|
fcc.initialized = 1;
|
||||||
fcc.function_handler = method_ptr;
|
fcc.function_handler = method_ptr;
|
||||||
fcc.calling_scope = ce;
|
fcc.calling_scope = ce;
|
||||||
fcc.called_scope = ce;
|
fcc.called_scope = ce;
|
||||||
fcc.object_ptr = value;
|
fcc.object_ptr = value;
|
||||||
|
|
||||||
jmp_buf env;
|
|
||||||
jmp_buf *old_env;
|
|
||||||
int val = 0;
|
|
||||||
bool installed_handler = false;
|
|
||||||
|
|
||||||
/* If this is the first level call from V8 back to PHP, install a
|
|
||||||
* handler for fatal errors; we must fall back through V8 to keep
|
|
||||||
* it from crashing. */
|
|
||||||
if (V8JSG(unwind_env) == NULL) {
|
|
||||||
installed_handler = true;
|
|
||||||
V8JSG(old_error_handler) = zend_error_cb;
|
|
||||||
zend_error_cb = php_v8js_error_handler;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* inner call, stash unwind env */
|
|
||||||
old_env = V8JSG(unwind_env);
|
|
||||||
}
|
|
||||||
|
|
||||||
val = setjmp (env);
|
|
||||||
V8JSG(unwind_env) = &env;
|
|
||||||
|
|
||||||
if (!val) {
|
|
||||||
/* Call the method */
|
|
||||||
zend_call_function(&fci, &fcc TSRMLS_CC);
|
zend_call_function(&fci, &fcc TSRMLS_CC);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (installed_handler) {
|
isolate->Enter();
|
||||||
/* leaving out-most frame, restore original handler. */
|
|
||||||
zend_error_cb = V8JSG(old_error_handler);
|
|
||||||
V8JSG(unwind_env) = NULL;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* leaving inner frame, restore unwind env and jump. */
|
|
||||||
V8JSG(unwind_env) = old_env;
|
|
||||||
|
|
||||||
if (V8JSG(fatal_error_abort)) {
|
|
||||||
longjmp(*V8JSG(unwind_env), 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (V8JSG(fatal_error_abort)) {
|
|
||||||
v8::V8::TerminateExecution(isolate);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
zend_catch {
|
||||||
isolate->Enter();
|
v8::V8::TerminateExecution(isolate);
|
||||||
|
V8JSG(fatal_error_abort) = 1;
|
||||||
|
}
|
||||||
|
zend_end_try();
|
||||||
|
|
||||||
failure:
|
failure:
|
||||||
/* Cleanup */
|
/* Cleanup */
|
||||||
|
Loading…
Reference in New Issue
Block a user