Index: test/cctest/test-debug.cc |
diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc |
index cf32d2ce5c6c2c6222b19c2d979e6c5fdb3c1535..8431b3618e684ff80f6986ef383df87c9cd64ca9 100644 |
--- a/test/cctest/test-debug.cc |
+++ b/test/cctest/test-debug.cc |
@@ -7425,3 +7425,49 @@ TEST(DebugBreakStackTrace) { |
" }" |
"})()"); |
} |
+ |
+ |
+v8::internal::Semaphore terminate_requested_semaphore(0); |
+v8::internal::Semaphore terminate_fired_semaphore(0); |
+bool terminate_already_fired = false; |
+ |
+ |
+static void DebugBreakTriggerTerminate( |
+ const v8::Debug::EventDetails& event_details) { |
+ if (event_details.GetEvent() != v8::Break || terminate_already_fired) return; |
+ terminate_requested_semaphore.Signal(); |
+ // Wait for at most 2 seconds for the terminate request. |
+ CHECK(terminate_fired_semaphore.WaitFor(i::TimeDelta::FromSeconds(2))); |
+ terminate_already_fired = true; |
+ v8::internal::Isolate* isolate = |
+ v8::Utils::OpenHandle(*event_details.GetEventContext())->GetIsolate(); |
+ CHECK(isolate->stack_guard()->CheckTerminateExecution()); |
+} |
+ |
+ |
+class TerminationThread : public v8::internal::Thread { |
+ public: |
+ explicit TerminationThread(v8::Isolate* isolate) : Thread("terminator"), |
+ isolate_(isolate) { } |
+ |
+ virtual void Run() { |
+ terminate_requested_semaphore.Wait(); |
+ v8::V8::TerminateExecution(isolate_); |
+ terminate_fired_semaphore.Signal(); |
+ } |
+ |
+ private: |
+ v8::Isolate* isolate_; |
+}; |
+ |
+ |
+TEST(DebugBreakOffThreadTerminate) { |
+ DebugLocalContext env; |
+ v8::Isolate* isolate = env->GetIsolate(); |
+ v8::HandleScope scope(isolate); |
+ v8::Debug::SetDebugEventListener(DebugBreakTriggerTerminate); |
+ TerminationThread terminator(isolate); |
+ terminator.Start(); |
+ v8::Debug::DebugBreak(isolate); |
+ CompileRun("while (true);"); |
+} |