[Lldb-commits] [lldb] r284795 - Fix a race condition between "ephemeral watchpoint disable/enable" and continue in commands.

Jim Ingham via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 20 17:06:39 PDT 2016


Author: jingham
Date: Thu Oct 20 19:06:38 2016
New Revision: 284795

URL: http://llvm.org/viewvc/llvm-project?rev=284795&view=rev
Log:
Fix a race condition between "ephemeral watchpoint disable/enable" and continue in commands.

Also, watchpoint commands, like breakpoint commands, need to run in async mode.

This was causing intermittent failures in TestWatchpointCommandPython.py, which is now solid.

Modified:
    lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py
    lldb/trunk/source/Breakpoint/Watchpoint.cpp
    lldb/trunk/source/Target/StopInfo.cpp

Modified: lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py?rev=284795&r1=284794&r2=284795&view=diff
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py (original)
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/watchpoint/watchpoint_commands/command/TestWatchpointCommandPython.py Thu Oct 20 19:06:38 2016
@@ -54,9 +54,6 @@ class WatchpointPythonCommandTestCase(Te
         # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
         lldbutil.run_break_set_by_file_and_line(
             self, None, self.line, num_expected_locations=1)
-#        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
-#            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
-#                       (self.source, self.line))#
 
         # Run the program.
         self.runCmd("run", RUN_SUCCEEDED)
@@ -131,9 +128,6 @@ class WatchpointPythonCommandTestCase(Te
         # Add a breakpoint to set a watchpoint when stopped on the breakpoint.
         lldbutil.run_break_set_by_file_and_line(
             self, None, self.line, num_expected_locations=1)
-#        self.expect("breakpoint set -l %d" % self.line, BREAKPOINT_CREATED,
-#            startstr = "Breakpoint created: 1: file ='%s', line = %d, locations = 1" %
-#                       (self.source, self.line))#
 
         # Run the program.
         self.runCmd("run", RUN_SUCCEEDED)
@@ -177,3 +171,4 @@ class WatchpointPythonCommandTestCase(Te
         # second hit and set it to 999
         self.expect("frame variable --show-globals cookie",
                     substrs=['(int32_t)', 'cookie = 999'])
+

Modified: lldb/trunk/source/Breakpoint/Watchpoint.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/Watchpoint.cpp?rev=284795&r1=284794&r2=284795&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/Watchpoint.cpp (original)
+++ lldb/trunk/source/Breakpoint/Watchpoint.cpp Thu Oct 20 19:06:38 2016
@@ -232,7 +232,7 @@ void Watchpoint::TurnOffEphemeralMode()
 }
 
 bool Watchpoint::IsDisabledDuringEphemeralMode() {
-  return m_disabled_count > 1;
+  return m_disabled_count > 1 && m_is_ephemeral;
 }
 
 void Watchpoint::SetEnabled(bool enabled, bool notify) {

Modified: lldb/trunk/source/Target/StopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/StopInfo.cpp?rev=284795&r1=284794&r2=284795&view=diff
==============================================================================
--- lldb/trunk/source/Target/StopInfo.cpp (original)
+++ lldb/trunk/source/Target/StopInfo.cpp Thu Oct 20 19:06:38 2016
@@ -557,27 +557,45 @@ public:
   // performing watchpoint actions.
   class WatchpointSentry {
   public:
-    WatchpointSentry(Process *p, Watchpoint *w) : process(p), watchpoint(w) {
-      if (process && watchpoint) {
+    WatchpointSentry(ProcessSP p_sp, WatchpointSP w_sp) : process_sp(p_sp), 
+                     watchpoint_sp(w_sp) {
+      if (process_sp && watchpoint_sp) {
         const bool notify = false;
-        watchpoint->TurnOnEphemeralMode();
-        process->DisableWatchpoint(watchpoint, notify);
+        watchpoint_sp->TurnOnEphemeralMode();
+        process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
+        process_sp->AddPreResumeAction(SentryPreResumeAction, this);
       }
     }
-
-    ~WatchpointSentry() {
-      if (process && watchpoint) {
-        if (!watchpoint->IsDisabledDuringEphemeralMode()) {
-          const bool notify = false;
-          process->EnableWatchpoint(watchpoint, notify);
+    
+    void DoReenable() {
+      if (process_sp && watchpoint_sp) {
+        bool was_disabled = watchpoint_sp->IsDisabledDuringEphemeralMode();
+        watchpoint_sp->TurnOffEphemeralMode();
+        const bool notify = false;
+        if (was_disabled) {
+          process_sp->DisableWatchpoint(watchpoint_sp.get(), notify);
+        } else {
+          process_sp->EnableWatchpoint(watchpoint_sp.get(), notify);
         }
-        watchpoint->TurnOffEphemeralMode();
       }
     }
+    
+    ~WatchpointSentry() {
+        DoReenable();
+        if (process_sp)
+            process_sp->ClearPreResumeAction(SentryPreResumeAction, this);
+    }
+    
+    static bool SentryPreResumeAction(void *sentry_void) {
+        WatchpointSentry *sentry = (WatchpointSentry *) sentry_void;
+        sentry->DoReenable();
+        return true;
+    }
 
   private:
-    Process *process;
-    Watchpoint *watchpoint;
+    ProcessSP process_sp;
+    WatchpointSP watchpoint_sp;
+    bool sentry_triggered = false;
   };
 
   StopInfoWatchpoint(Thread &thread, break_id_t watch_id,
@@ -659,12 +677,12 @@ protected:
               GetValue()));
       if (wp_sp) {
         ExecutionContext exe_ctx(thread_sp->GetStackFrameAtIndex(0));
-        Process *process = exe_ctx.GetProcessPtr();
+        ProcessSP process_sp = exe_ctx.GetProcessSP();
 
         // This sentry object makes sure the current watchpoint is disabled
         // while performing watchpoint actions,
         // and it is then enabled after we are finished.
-        WatchpointSentry sentry(process, wp_sp.get());
+        WatchpointSentry sentry(process_sp, wp_sp);
 
         {
           // check if this process is running on an architecture where
@@ -672,10 +690,10 @@ protected:
           // before the associated instruction runs. if so, disable the WP,
           // single-step and then
           // re-enable the watchpoint
-          if (process) {
+          if (process_sp) {
             uint32_t num;
             bool wp_triggers_after;
-            if (process->GetWatchpointSupportInfo(num, wp_triggers_after)
+            if (process_sp->GetWatchpointSupportInfo(num, wp_triggers_after)
                     .Success()) {
               if (!wp_triggers_after) {
                 StopInfoSP stored_stop_info_sp = thread_sp->GetStopInfo();
@@ -689,10 +707,10 @@ protected:
                 new_plan_sp->SetIsMasterPlan(true);
                 new_plan_sp->SetOkayToDiscard(false);
                 new_plan_sp->SetPrivate(true);
-                process->GetThreadList().SetSelectedThreadByID(
+                process_sp->GetThreadList().SetSelectedThreadByID(
                     thread_sp->GetID());
-                process->ResumeSynchronous(nullptr);
-                process->GetThreadList().SetSelectedThreadByID(
+                process_sp->ResumeSynchronous(nullptr);
+                process_sp->GetThreadList().SetSelectedThreadByID(
                     thread_sp->GetID());
                 thread_sp->SetStopInfo(stored_stop_info_sp);
               }
@@ -739,6 +757,8 @@ protected:
         if (wp_sp->GetHitCount() <= wp_sp->GetIgnoreCount())
           m_should_stop = false;
 
+        Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
+
         if (m_should_stop && wp_sp->GetConditionText() != nullptr) {
           // We need to make sure the user sees any parse errors in their
           // condition, so we'll hook the
@@ -778,7 +798,6 @@ protected:
               }
             }
           } else {
-            Debugger &debugger = exe_ctx.GetTargetRef().GetDebugger();
             StreamSP error_sp = debugger.GetAsyncErrorStream();
             error_sp->Printf(
                 "Stopped due to an error evaluating condition of watchpoint ");
@@ -800,8 +819,20 @@ protected:
         // If the condition says to stop, we run the callback to further decide
         // whether to stop.
         if (m_should_stop) {
+            // FIXME: For now the callbacks have to run in async mode - the
+            // first time we restart we need
+            // to get out of there.  So set it here.
+            // When we figure out how to nest watchpoint hits then this will
+            // change.
+
+          bool old_async = debugger.GetAsyncExecution();
+          debugger.SetAsyncExecution(true);
+          
           StoppointCallbackContext context(event_ptr, exe_ctx, false);
           bool stop_requested = wp_sp->InvokeCallback(&context);
+          
+          debugger.SetAsyncExecution(old_async);
+          
           // Also make sure that the callback hasn't continued the target.
           // If it did, when we'll set m_should_stop to false and get out of
           // here.




More information about the lldb-commits mailing list