Skip to content

Commit

Permalink
v8: port fbff705 from v0.10 to v0.12
Browse files Browse the repository at this point in the history
this was cherry-picked manually

    fbff705
    Add v8::Isolate::SetAbortOnUncaughtException() so the user can be
    notified when an uncaught exception has bubbled.

    Fixes: nodejs/node-v0.x-archive#8877
    PR-URL: nodejs/node-v0.x-archive#25835
    Reviewed-By: misterdjules - Julien Gilli <jgilli@nodejs.org>
  • Loading branch information
jBarz committed Feb 1, 2017
1 parent c83d0b7 commit 6e7b7a1
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 10 deletions.
11 changes: 11 additions & 0 deletions include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -4209,6 +4209,17 @@ class V8_EXPORT Isolate {
*/
static Isolate* GetCurrent();

/**
* Custom callback used by embedders to help V8 determine if it should abort
* when it throws and no internal handler can catch the exception.
* If FLAG_abort_on_uncaught_exception is true, then V8 will abort if either:
* - no custom callback is set.
* - the custom callback set returns true.
* Otherwise it won't abort.
*/
typedef bool (*abort_on_uncaught_exception_t)(Isolate*);
void SetAbortOnUncaughtException(abort_on_uncaught_exception_t callback);

/**
* Methods below this point require holding a lock (using Locker) in
* a multi-threaded environment.
Expand Down
7 changes: 7 additions & 0 deletions src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6599,6 +6599,13 @@ void Isolate::Enter() {
}


void Isolate::SetAbortOnUncaughtException(
abort_on_uncaught_exception_t callback) {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->SetAbortOnUncaughtException(callback);
}


void Isolate::Exit() {
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this);
isolate->Exit();
Expand Down
41 changes: 31 additions & 10 deletions src/isolate.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,7 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
// It's not safe to try to make message objects or collect stack traces
// while the bootstrapper is active since the infrastructure may not have
// been properly initialized.
#pragma convert("ISO8859-1")
if (!bootstrapping) {
Handle<JSArray> stack_trace_object;
if (capture_stack_trace_for_uncaught_exceptions_) {
Expand All @@ -1066,9 +1067,9 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
}

Handle<Object> exception_arg = exception_handle;
// If the exception argument is a custom object, turn it into a string
// before throwing as uncaught exception. Note that the pending
// exception object to be set later must not be turned into a string.
// If the abort-on-uncaught-exception flag is specified, and if the
// exception is not caught by JavaScript (even when an external handler is
// present).
if (exception_arg->IsJSObject() && !IsErrorObject(exception_arg)) {
MaybeHandle<Object> maybe_exception =
Execution::ToDetailString(this, exception_arg);
Expand Down Expand Up @@ -1097,12 +1098,24 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
if (fatal_exception_depth == 0 &&
FLAG_abort_on_uncaught_exception &&
(report_exception || can_be_caught_externally)) {
fatal_exception_depth++;
PrintF(stderr,
"\x6c\xa2\xa\xaF\x52\x4f\x4d\xa",
MessageHandler::GetLocalizedMessage(this, message_obj).get());
PrintCurrentStackTrace(stderr);
base::OS::Abort();
// If the embedder didn't specify a custom uncaught exception callback,
// or if the custom callback determined that V8 should abort, then
// abort
bool should_abort = !abort_on_uncaught_exception_callback_ ||
abort_on_uncaught_exception_callback_(
reinterpret_cast<v8::Isolate*>(this)
);

if (should_abort) {
fatal_exception_depth++;
// This flag is intended for use by JavaScript developers, so
// print a user-friendly stack trace (not an internal one).
FPrintASCII(stderr,
"%s\n\nFROM\n",
MessageHandler::GetLocalizedMessage(this, message_obj).get());
PrintCurrentStackTrace(stderr);
base::OS::Abort();
}
}
} else if (location != NULL && !location->script().is_null()) {
// We are bootstrapping and caught an error where the location is set
Expand Down Expand Up @@ -1145,6 +1158,7 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) {
}
#endif
}
#pragma convert(pop)
}

// Save the message for reporting if the the exception remains uncaught.
Expand Down Expand Up @@ -1299,6 +1313,12 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions(
}


void Isolate::SetAbortOnUncaughtException(
v8::Isolate::abort_on_uncaught_exception_t callback) {
abort_on_uncaught_exception_callback_ = callback;
}


Handle<Context> Isolate::native_context() {
return handle(context()->native_context());
}
Expand Down Expand Up @@ -1474,7 +1494,8 @@ Isolate::Isolate()
num_sweeper_threads_(0),
stress_deopt_count_(0),
next_optimization_id_(0),
use_counter_callback_(NULL) {
use_counter_callback_(NULL),
abort_on_uncaught_exception_callback_(NULL) {
id_ = base::NoBarrier_AtomicIncrement(&isolate_counter_, 1);
TRACE_ISOLATE(constructor);

Expand Down
5 changes: 5 additions & 0 deletions src/isolate.h
Original file line number Diff line number Diff line change
Expand Up @@ -717,6 +717,9 @@ class Isolate {
int frame_limit,
StackTrace::StackTraceOptions options);

typedef bool (*abort_on_uncaught_exception_t)(v8::Isolate*);
void SetAbortOnUncaughtException(abort_on_uncaught_exception_t callback);

void PrintCurrentStackTrace(FILE* out);
void PrintStack(StringStream* accumulator);
void PrintStack(FILE* out);
Expand Down Expand Up @@ -1341,6 +1344,8 @@ class Isolate {

v8::Isolate::UseCounterCallback use_counter_callback_;

abort_on_uncaught_exception_t abort_on_uncaught_exception_callback_;

friend class ExecutionAccess;
friend class HandleScopeImplementer;
friend class IsolateInitializer;
Expand Down

0 comments on commit 6e7b7a1

Please sign in to comment.