Cope with the case where the user-supplied callbacks want the watchpoint itself to be disabled!
Previously we put a WatchpointSentry object within StopInfo.cpp to disable-and-then-enable the watchpoint itself
while we are performing the actions associated with the triggered watchpoint, which can cause the user-initiated
watchpoint disabling action to be negated.

Add a test case to verify that a watchpoint can be disabled during the callbacks.


git-svn-id: https://llvm.org/svn/llvm-project/lldb/trunk@162483 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Breakpoint/Watchpoint.cpp b/source/Breakpoint/Watchpoint.cpp
index 3736adb..ca5503f 100644
--- a/source/Breakpoint/Watchpoint.cpp
+++ b/source/Breakpoint/Watchpoint.cpp
@@ -30,6 +30,7 @@
     m_is_hardware(hardware),
     m_is_watch_variable(false),
     m_is_ephemeral(false),
+    m_disabled_count(0),
     m_watch_read(0),
     m_watch_write(0),
     m_watch_was_read(0),
@@ -322,6 +323,14 @@
 Watchpoint::TurnOffEphemeralMode()
 {
     m_is_ephemeral = false;
+    // Leaving ephemeral mode, reset the m_disabled_count!
+    m_disabled_count = 0;
+}
+
+bool
+Watchpoint::IsDisabledDuringEphemeralMode()
+{
+    return m_disabled_count > 1;
 }
 
 void
@@ -331,6 +340,9 @@
     {
         if (!m_is_ephemeral)
             SetHardwareIndex(LLDB_INVALID_INDEX32);
+        else
+            ++m_disabled_count;
+
         // Don't clear the snapshots for now.
         // Within StopInfo.cpp, we purposely do disable/enable watchpoint while performing watchpoint actions.
         //ClearSnapshots();
diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 07536c7..6089b83 100644
--- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -2281,6 +2281,10 @@
         {
             if (log)
                 log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %llu) addr = 0x%8.8llx -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
+            // See also 'class WatchpointSentry' within StopInfo.cpp.
+            // This disabling attempt might come from the user-supplied actions, we'll route it in order for
+            // the watchpoint object to intelligently process this action.
+            wp->SetEnabled(false);
             return error;
         }
         
diff --git a/source/Target/StopInfo.cpp b/source/Target/StopInfo.cpp
index 400829f..01d8ba9 100644
--- a/source/Target/StopInfo.cpp
+++ b/source/Target/StopInfo.cpp
@@ -463,7 +463,8 @@
         {
             if (process && watchpoint)
             {
-                process->EnableWatchpoint(watchpoint);
+                if (!watchpoint->IsDisabledDuringEphemeralMode())
+                    process->EnableWatchpoint(watchpoint);
                 watchpoint->TurnOffEphemeralMode();
             }
         }