]>
Commit | Line | Data |
---|---|---|
f8f77d43 ER |
1 | # Fix issues with abort on uncaught exception |
2 | # https://github.com/joyent/node/pull/8666 | |
3 | # https://github.com/joyent/node/issues/8631 | |
4 | # https://github.com/joyent/node/issues/8630 | |
5 | From fbff7054a47551387a99244e2cf0631f30406798 Mon Sep 17 00:00:00 2001 | |
6 | From: Trevor Norris <trev.norris@gmail.com> | |
7 | Date: Tue, 18 Nov 2014 16:37:54 -0800 | |
8 | Subject: [PATCH] v8: add api for aborting on uncaught exception | |
9 | ||
10 | Add v8::Isolate::SetAbortOnUncaughtException() so the user can be | |
11 | notified when an uncaught exception has bubbled. | |
12 | ||
13 | PR-URL: https://github.com/joyent/node/pull/8666 | |
14 | Reviewed-by: Trevor Norris <trev.norris@gmail.com> | |
15 | --- | |
16 | include/v8.h | 11 +++++++++++ | |
17 | src/api.cc | 5 +++++ | |
18 | src/isolate.cc | 33 +++++++++++++++++++++++---------- | |
19 | src/isolate.h | 5 +++++ | |
20 | 4 files changed, 44 insertions(+), 10 deletions(-) | |
21 | ||
22 | diff --git a/include/v8.h b/include/v8.h | |
23 | index 71a0d01..e229ed9 100644 | |
24 | --- a/include/v8.h | |
25 | +++ b/include/v8.h | |
26 | @@ -2842,6 +2842,17 @@ class V8EXPORT Isolate { | |
27 | static Isolate* GetCurrent(); | |
28 | ||
29 | /** | |
30 | + * Custom callback used by embedders to help V8 determine if it should abort | |
31 | + * when it throws and no internal handler can catch the exception. | |
32 | + * If FLAG_abort_on_uncaught_exception is true, then V8 will abort if either: | |
33 | + * - no custom callback is set. | |
34 | + * - the custom callback set returns true. | |
35 | + * Otherwise it won't abort. | |
36 | + */ | |
37 | + typedef bool (*abort_on_uncaught_exception_t)(); | |
38 | + void SetAbortOnUncaughtException(abort_on_uncaught_exception_t callback); | |
39 | + | |
40 | + /** | |
41 | * Methods below this point require holding a lock (using Locker) in | |
42 | * a multi-threaded environment. | |
43 | */ | |
44 | diff --git a/src/api.cc b/src/api.cc | |
45 | index 96d564f..4b1aa67 100644 | |
46 | --- a/src/api.cc | |
47 | +++ b/src/api.cc | |
48 | @@ -5550,6 +5550,11 @@ void Isolate::Enter() { | |
49 | isolate->Enter(); | |
50 | } | |
51 | ||
52 | +void Isolate::SetAbortOnUncaughtException( | |
53 | + abort_on_uncaught_exception_t callback) { | |
54 | + i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); | |
55 | + isolate->SetAbortOnUncaughtException(callback); | |
56 | +} | |
57 | ||
58 | void Isolate::Exit() { | |
59 | i::Isolate* isolate = reinterpret_cast<i::Isolate*>(this); | |
60 | diff --git a/src/isolate.cc b/src/isolate.cc | |
61 | index 5a5293e..0b38616 100644 | |
62 | --- a/src/isolate.cc | |
63 | +++ b/src/isolate.cc | |
64 | @@ -1152,18 +1152,26 @@ void Isolate::DoThrow(Object* exception, MessageLocation* location) { | |
65 | thread_local_top()->pending_message_end_pos_ = location->end_pos(); | |
66 | } | |
67 | ||
68 | - // If the abort-on-uncaught-exception flag is specified, abort on any | |
69 | - // exception not caught by JavaScript, even when an external handler is | |
70 | - // present. This flag is intended for use by JavaScript developers, so | |
71 | - // print a user-friendly stack trace (not an internal one). | |
72 | + // If the abort-on-uncaught-exception flag is specified, and if the | |
73 | + // exception is not caught by JavaScript (even when an external handler is | |
74 | + // present). | |
75 | if (fatal_exception_depth == 0 && | |
76 | FLAG_abort_on_uncaught_exception && | |
77 | (report_exception || can_be_caught_externally)) { | |
78 | - fatal_exception_depth++; | |
79 | - fprintf(stderr, "%s\n\nFROM\n", | |
80 | - *MessageHandler::GetLocalizedMessage(message_obj)); | |
81 | - PrintCurrentStackTrace(stderr); | |
82 | - OS::Abort(); | |
83 | + // If the embedder didn't specify a custom uncaught exception callback, | |
84 | + // or if the custom callback determined that V8 should abort, then | |
85 | + // abort | |
86 | + bool should_abort = !abort_on_uncaught_exception_callback_ || | |
87 | + abort_on_uncaught_exception_callback_(); | |
88 | + if (should_abort) { | |
89 | + fatal_exception_depth++; | |
90 | + // This flag is intended for use by JavaScript developers, so | |
91 | + // print a user-friendly stack trace (not an internal one). | |
92 | + fprintf(stderr, "%s\n\nFROM\n", | |
93 | + *MessageHandler::GetLocalizedMessage(message_obj)); | |
94 | + PrintCurrentStackTrace(stderr); | |
95 | + OS::Abort(); | |
96 | + } | |
97 | } | |
98 | } else if (location != NULL && !location->script().is_null()) { | |
99 | // We are bootstrapping and caught an error where the location is set | |
100 | @@ -1339,6 +1347,10 @@ void Isolate::SetCaptureStackTraceForUncaughtExceptions( | |
101 | stack_trace_for_uncaught_exceptions_options_ = options; | |
102 | } | |
103 | ||
104 | +void Isolate::SetAbortOnUncaughtException( | |
105 | + v8::Isolate::abort_on_uncaught_exception_t callback) { | |
106 | + abort_on_uncaught_exception_callback_ = callback; | |
107 | +} | |
108 | ||
109 | bool Isolate::is_out_of_memory() { | |
110 | if (has_pending_exception()) { | |
111 | @@ -1534,7 +1546,8 @@ Isolate::Isolate() | |
112 | date_cache_(NULL), | |
113 | context_exit_happened_(false), | |
114 | deferred_handles_head_(NULL), | |
115 | - optimizing_compiler_thread_(this) { | |
116 | + optimizing_compiler_thread_(this), | |
117 | + abort_on_uncaught_exception_callback_(NULL) { | |
118 | TRACE_ISOLATE(constructor); | |
119 | ||
120 | memset(isolate_addresses_, 0, | |
121 | diff --git a/src/isolate.h b/src/isolate.h | |
122 | index 2769ca7..8719aa1 100644 | |
123 | --- a/src/isolate.h | |
124 | +++ b/src/isolate.h | |
125 | @@ -692,6 +692,9 @@ class Isolate { | |
126 | int frame_limit, | |
127 | StackTrace::StackTraceOptions options); | |
128 | ||
129 | + typedef bool (*abort_on_uncaught_exception_t)(); | |
130 | + void SetAbortOnUncaughtException(abort_on_uncaught_exception_t callback); | |
131 | + | |
132 | // Tells whether the current context has experienced an out of memory | |
133 | // exception. | |
134 | bool is_out_of_memory(); | |
135 | @@ -1292,6 +1295,8 @@ class Isolate { | |
136 | DeferredHandles* deferred_handles_head_; | |
137 | OptimizingCompilerThread optimizing_compiler_thread_; | |
138 | ||
139 | + abort_on_uncaught_exception_t abort_on_uncaught_exception_callback_; | |
140 | + | |
141 | friend class ExecutionAccess; | |
142 | friend class HandleScopeImplementer; | |
143 | friend class IsolateInitializer; |