Author: jingham
Date: Tue Jan 14 21:32:42 2014
New Revision: 199290

URL: http://llvm.org/viewvc/llvm-project?rev=199290&view=rev
Log:
Fix a bug where if we stop but nobody says there was a reason for the stop, we 
would return
control to the user anyway.  This was put in to handle monitors that would say 
there was no
stop reason when you first attached to them.  But it broke the case where you 
hit a thread specific
breakpoint on many threads, but NOT the one specified in the breakpoint.  I 
work around this
by only doing the junky override when the StopID is 0 - i.e. on first attach.

This commit also adds a test for thread specific breakpoints.

Added:
    lldb/trunk/test/functionalities/thread/thread_specific_break/
    lldb/trunk/test/functionalities/thread/thread_specific_break/Makefile
    
lldb/trunk/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
    lldb/trunk/test/functionalities/thread/thread_specific_break/main.c
Modified:
    lldb/trunk/source/Target/ThreadList.cpp

Modified: lldb/trunk/source/Target/ThreadList.cpp
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/ThreadList.cpp?rev=199290&r1=199289&r2=199290&view=diff
==============================================================================
--- lldb/trunk/source/Target/ThreadList.cpp (original)
+++ lldb/trunk/source/Target/ThreadList.cpp Tue Jan 14 21:32:42 2014
@@ -293,17 +293,31 @@ ThreadList::ShouldStop (Event *event_ptr
     {
         ThreadSP thread_sp(*pos);
         
-        did_anybody_stop_for_a_reason |= thread_sp->ThreadStoppedForAReason();
+        // We should never get a stop for which no thread had a stop reason, 
but sometimes we do see this -
+        // for instance when we first connect to a remote stub.  In that case 
we should stop, since we can't figure out
+        // the right thing to do and stopping gives the user control over what 
to do in this instance.
+        //
+        // Note, this causes a problem when you have a thread specific 
breakpoint, and a bunch of threads hit the breakpoint,
+        // but not the thread which we are waiting for.  All the threads that 
are not "supposed" to hit the breakpoint
+        // are marked as having no stop reason, which is right, they should 
not show a stop reason.  But that triggers this
+        // code and causes us to stop seemingly for no reason.
+        //
+        // Since the only way we ever saw this error was on first attach, I'm 
only going to trigger set did_anybody_stop_for_a_reason
+        // to true unless this is the first stop.
+        //
+        // If this becomes a problem, we'll have to have another StopReason 
like "StopInfoHidden" which will look invalid
+        // everywhere but at this check.
+    
+        if (thread_sp->GetProcess()->GetStopID() != 0)
+            did_anybody_stop_for_a_reason = true;
+        else
+            did_anybody_stop_for_a_reason |= 
thread_sp->ThreadStoppedForAReason();
         
         const bool thread_should_stop = thread_sp->ShouldStop(event_ptr);
         if (thread_should_stop)
             should_stop |= true;
     }
 
-    // We should never get a stop for which no thread had a stop reason, but 
sometimes we do see this -
-    // for instance when we first connect to a remote stub.  In that case we 
should stop, since we can't figure out
-    // the right thing to do and stopping gives the user control over what to 
do in this instance.
-    
     if (!should_stop && !did_anybody_stop_for_a_reason)
     {
         should_stop = true;

Added: lldb/trunk/test/functionalities/thread/thread_specific_break/Makefile
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/thread_specific_break/Makefile?rev=199290&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/thread/thread_specific_break/Makefile 
(added)
+++ lldb/trunk/test/functionalities/thread/thread_specific_break/Makefile Tue 
Jan 14 21:32:42 2014
@@ -0,0 +1,5 @@
+LEVEL = ../../../make
+
+C_SOURCES := main.c
+
+include $(LEVEL)/Makefile.rules

Added: 
lldb/trunk/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py?rev=199290&view=auto
==============================================================================
--- 
lldb/trunk/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
 (added)
+++ 
lldb/trunk/test/functionalities/thread/thread_specific_break/TestThreadSpecificBreakpoint.py
 Tue Jan 14 21:32:42 2014
@@ -0,0 +1,77 @@
+"""
+Test that we obey thread conditioned breakpoints.
+"""
+
+import os, time
+import re
+import unittest2
+import lldb, lldbutil
+from lldbtest import *
+
+class ThreadSpecificBreakTestCase(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @unittest2.skipUnless(sys.platform.startswith("darwin"), "requires Darwin")
+    @python_api_test
+    @dsym_test
+    def test_with_dsym_python(self):
+        """Test that we obey thread conditioned breakpoints."""
+        self.buildDsym()
+        self.do_thread_specific_break()
+
+    @python_api_test
+    @dwarf_test
+    def test_with_dwarf_python(self):
+        """Test that we obey thread conditioned breakpoints."""
+        self.buildDwarf()
+        self.do_thread_specific_break()
+
+    def do_thread_specific_break(self):
+        """Test that we obey thread conditioned breakpoints."""
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        self.dbg.HandleCommand ("log enable -f /tmp/lldb-testsuite-log.txt 
lldb step breakpoint process") 
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        main_source_spec = lldb.SBFileSpec ("main.c")
+
+        # Set a breakpoint in the thread body, and make it active for only the 
first thread.
+        break_thread_body = target.BreakpointCreateBySourceRegex ("Break here 
in thread body.", main_source_spec)
+        self.assertTrue (break_thread_body.IsValid() and 
break_thread_body.GetNumLocations() > 0, "Failed to set thread body 
breakpoint.")
+
+        process = target.LaunchSimple (None, None, 
self.get_process_working_directory())
+
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        threads = lldbutil.get_threads_stopped_at_breakpoint (process, 
break_thread_body)
+        
+        victim_thread = threads[0]
+
+        # Pick one of the threads, and change the breakpoint so it ONLY stops 
for this thread,
+        # but add a condition that it won't stop for this thread's my_value.  
The other threads
+        # pass the condition, so they should stop, but if the 
thread-specification is working
+        # they should not stop.  So nobody should hit the breakpoint anymore, 
and we should
+        # just exit cleanly.
+
+        frame = victim_thread.GetFrameAtIndex(0)
+        value = frame.FindVariable("my_value").GetValueAsSigned(0)
+        self.assertTrue (value > 0 and value < 11, "Got a reasonable value for 
my_value.")
+
+        cond_string = "my_value != %d"%(value)
+
+        break_thread_body.SetThreadID(victim_thread.GetThreadID())
+        break_thread_body.SetCondition (cond_string)
+
+        process.Continue()
+
+        next_stop_state = process.GetState()
+        self.assertTrue (next_stop_state == lldb.eStateExited, "We should have 
not hit the breakpoint again.")
+        
+
+if __name__ == '__main__':
+    import atexit
+    lldb.SBDebugger.Initialize()
+    atexit.register(lambda: lldb.SBDebugger.Terminate())
+    unittest2.main()

Added: lldb/trunk/test/functionalities/thread/thread_specific_break/main.c
URL: 
http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/thread/thread_specific_break/main.c?rev=199290&view=auto
==============================================================================
--- lldb/trunk/test/functionalities/thread/thread_specific_break/main.c (added)
+++ lldb/trunk/test/functionalities/thread/thread_specific_break/main.c Tue Jan 
14 21:32:42 2014
@@ -0,0 +1,38 @@
+#include <pthread.h>
+#include <unistd.h>
+
+void *
+thread_function (void *thread_marker)
+{
+  int keep_going = 1; 
+  int my_value = *((int *)thread_marker);
+  int counter = 0;
+
+  while (counter < 20)
+    {
+      counter++; // Break here in thread body.
+      usleep (10);
+    }
+  return NULL;
+}
+
+
+int 
+main ()
+{
+
+  pthread_t threads[10];
+
+  int thread_value = 0;
+
+  for (int i = 0; i < 10; i++)
+    {
+      thread_value += 1;
+      pthread_create (&threads[i], NULL, &thread_function, &thread_value);
+    }
+
+  for (int i = 0; i < 10; i++)
+    pthread_join (threads[i], NULL);
+
+  return 0;
+}


_______________________________________________
lldb-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/lldb-commits

Reply via email to