Revision: 21605
Author:   [email protected]
Date:     Mon Jun  2 12:07:37 2014 UTC
Log:      Release execution lock before dispatching interrupt handling.

[email protected]

Review URL: https://codereview.chromium.org/309533009
http://code.google.com/p/v8/source/detail?r=21605

Modified:
 /branches/bleeding_edge/src/debug.cc
 /branches/bleeding_edge/src/execution.cc
 /branches/bleeding_edge/src/execution.h
 /branches/bleeding_edge/test/cctest/test-debug.cc

=======================================
--- /branches/bleeding_edge/src/debug.cc        Mon Jun  2 11:41:50 2014 UTC
+++ /branches/bleeding_edge/src/debug.cc        Mon Jun  2 12:07:37 2014 UTC
@@ -2541,6 +2541,8 @@
isolate_, isolate_->global_object(), constructor_name).ToHandleChecked();
   ASSERT(constructor->IsJSFunction());
   if (!constructor->IsJSFunction()) return MaybeHandle<Object>();
+ // We do not handle interrupts here. In particular, termination interrupts.
+  PostponeInterruptsScope no_interrupts(isolate_);
   return Execution::TryCall(Handle<JSFunction>::cast(constructor),
Handle<JSObject>(debug_context()->global_object()),
                             argc,
@@ -2852,6 +2854,9 @@
                                  Handle<JSObject> exec_state,
                                  Handle<JSObject> event_data,
                                  bool auto_continue) {
+  // Prevent other interrupts from triggering, for example API callbacks,
+  // while dispatching message handler callbacks.
+  PostponeInterruptsScope no_interrupts(isolate_);
   ASSERT(is_active_);
   HandleScope scope(isolate_);
   // Process the individual events.
=======================================
--- /branches/bleeding_edge/src/execution.cc    Mon Jun  2 11:41:50 2014 UTC
+++ /branches/bleeding_edge/src/execution.cc    Mon Jun  2 12:07:37 2014 UTC
@@ -366,13 +366,13 @@
 }


-bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag,
-                                        const ExecutionAccess& lock) {
+bool StackGuard::CheckAndClearInterrupt(InterruptFlag flag) {
+  ExecutionAccess access(isolate_);
   int flagbit = 1 << flag;
   bool result = (thread_local_.interrupt_flags_ & flagbit);
   thread_local_.interrupt_flags_ &= ~flagbit;
-  if (!should_postpone_interrupts(lock) && !has_pending_interrupts(lock)) {
-    reset_limits(lock);
+ if (!should_postpone_interrupts(access) && !has_pending_interrupts(access)) {
+    reset_limits(access);
   }
   return result;
 }
@@ -655,45 +655,42 @@


 Object* StackGuard::HandleInterrupts() {
-  bool has_api_interrupt = false;
   {
     ExecutionAccess access(isolate_);
     if (should_postpone_interrupts(access)) {
       return isolate_->heap()->undefined_value();
     }
+  }

-    if (CheckAndClearInterrupt(GC_REQUEST, access)) {
- isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
-    }
+  if (CheckAndClearInterrupt(GC_REQUEST)) {
+    isolate_->heap()->CollectAllGarbage(Heap::kNoGCFlags, "GC interrupt");
+  }

-    if (CheckDebugBreak() || CheckDebugCommand()) {
-      isolate_->debug()->DebugBreakHelper();
-    }
+  if (CheckDebugBreak() || CheckDebugCommand()) {
+    isolate_->debug()->DebugBreakHelper();
+  }

-    if (CheckAndClearInterrupt(TERMINATE_EXECUTION, access)) {
-      return isolate_->TerminateExecution();
-    }
-
-    if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES, access)) {
-      isolate_->heap()->DeoptMarkedAllocationSites();
-    }
-
-    if (CheckAndClearInterrupt(INSTALL_CODE, access)) {
-      ASSERT(isolate_->concurrent_recompilation_enabled());
-      isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
-    }
+  if (CheckAndClearInterrupt(TERMINATE_EXECUTION)) {
+    return isolate_->TerminateExecution();
+  }

-    has_api_interrupt = CheckAndClearInterrupt(API_INTERRUPT, access);
+  if (CheckAndClearInterrupt(DEOPT_MARKED_ALLOCATION_SITES)) {
+    isolate_->heap()->DeoptMarkedAllocationSites();
+  }

-    isolate_->counters()->stack_interrupts()->Increment();
-    isolate_->counters()->runtime_profiler_ticks()->Increment();
-    isolate_->runtime_profiler()->OptimizeNow();
+  if (CheckAndClearInterrupt(INSTALL_CODE)) {
+    ASSERT(isolate_->concurrent_recompilation_enabled());
+    isolate_->optimizing_compiler_thread()->InstallOptimizedFunctions();
   }

-  if (has_api_interrupt) {
+  if (CheckAndClearInterrupt(API_INTERRUPT)) {
     // Callback must be invoked outside of ExecusionAccess lock.
     isolate_->InvokeApiInterruptCallback();
   }
+
+  isolate_->counters()->stack_interrupts()->Increment();
+  isolate_->counters()->runtime_profiler_ticks()->Increment();
+  isolate_->runtime_profiler()->OptimizeNow();

   return isolate_->heap()->undefined_value();
 }
=======================================
--- /branches/bleeding_edge/src/execution.h     Mon Jun  2 11:41:50 2014 UTC
+++ /branches/bleeding_edge/src/execution.h     Mon Jun  2 12:07:37 2014 UTC
@@ -203,7 +203,7 @@
   bool CheckInterrupt(int flagbit);
   void RequestInterrupt(int flagbit);
   void ClearInterrupt(int flagbit);
- bool CheckAndClearInterrupt(InterruptFlag flag, const ExecutionAccess& lock);
+  bool CheckAndClearInterrupt(InterruptFlag flag);

   // You should hold the ExecutionAccess lock when calling this method.
   bool has_pending_interrupts(const ExecutionAccess& lock) {
=======================================
--- /branches/bleeding_edge/test/cctest/test-debug.cc Mon Jun 2 11:41:50 2014 UTC +++ /branches/bleeding_edge/test/cctest/test-debug.cc Mon Jun 2 12:07:37 2014 UTC
@@ -7425,3 +7425,49 @@
              "  }"
              "})()");
 }
+
+
+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);");
+}

--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
--- You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to