[Lldb-commits] [lldb] r289026 - When we interrupt a process, it was possible or the thread names

Jason Molenda via lldb-commits lldb-commits at lists.llvm.org
Wed Dec 7 22:27:30 PST 2016


Author: jmolenda
Date: Thu Dec  8 00:27:29 2016
New Revision: 289026

URL: http://llvm.org/viewvc/llvm-project?rev=289026&view=rev
Log:
When we interrupt a process, it was possible or the thread names
to not be set by Process::WillPublicStop() so the driver won't get
access to them.  The fix is straightforward, moving the call to
WillPublicStop above the early return for the interrupt case.  (the
interrupt case does an early return because the rest of the function
is concerned with running stop hooks etc and those are not applicable
when we've interrupted the process).

Also added a test case for it.  The test case is a little complicated
because I needed to drive lldb asynchronously to give the program
a chance to get up and running before I interrupt it.  Running to
a breakpoint was not sufficient to catch this bug.

<rdar://problem/22693778> 

Added:
    lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/
    lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/Makefile
    lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/TestInterruptThreadNames.py
    lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/main.c
Modified:
    lldb/trunk/source/Target/Process.cpp

Added: lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/Makefile?rev=289026&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/Makefile (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/Makefile Thu Dec  8 00:27:29 2016
@@ -0,0 +1,28 @@
+CC ?= clang
+ifeq "$(ARCH)" ""
+	ARCH = x86_64
+endif
+
+ifeq "$(OS)" ""
+	OS = $(shell uname -s)
+endif
+
+CFLAGS ?= -g -O0
+CWD := $(shell pwd)
+
+LIB_PREFIX := lib
+
+ifeq "$(OS)" "Darwin"
+	CFLAGS += -arch $(ARCH)
+endif
+
+all: a.out
+
+a.out: main.o
+	$(CC) $(CFLAGS) -o a.out main.o
+
+main.o: main.c
+	$(CC) $(CFLAGS) -c main.c
+
+clean:
+	rm -rf $(wildcard *.o *~ *.dylib *.so a.out *.dSYM)

Added: lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/TestInterruptThreadNames.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/TestInterruptThreadNames.py?rev=289026&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/TestInterruptThreadNames.py (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/TestInterruptThreadNames.py Thu Dec  8 00:27:29 2016
@@ -0,0 +1,116 @@
+"""Test that we get thread names when interrupting a process.""" 
+from __future__ import print_function
+
+
+import os
+import time
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestInterruptThreadNames(TestBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        # Call super's setUp().
+        TestBase.setUp(self)
+
+    @skipUnlessDarwin
+    @add_test_categories(['pyapi'])
+    def test_with_python_api(self):
+        """Test that we get thread names when interrupting a process."""
+        self.build()
+        exe = os.path.join(os.getcwd(), "a.out")
+
+        target = self.dbg.CreateTarget(exe)
+        self.assertTrue(target, VALID_TARGET)
+
+        launch_info = lldb.SBLaunchInfo(None)
+        error = lldb.SBError()
+        lldb.debugger.SetAsync(True)
+        process = target.Launch(launch_info, error)
+        self.assertTrue(process, PROCESS_IS_VALID)
+
+        listener = lldb.debugger.GetListener()
+        broadcaster = process.GetBroadcaster()
+        rc = broadcaster.AddListener(listener, lldb.SBProcess.eBroadcastBitStateChanged)
+        self.assertTrue(rc != 0, "Unable to add listener to process")
+        self.assertTrue(self.wait_for_running(process, listener), "Check that process is up and running")
+
+
+        inferior_set_up = lldb.SBValue()
+        retry = 5
+        while retry > 0:
+            time.sleep(1)
+            process.SendAsyncInterrupt()
+            self.assertTrue(self.wait_for_stop(process, listener), "Check that process is paused")
+            inferior_set_up = target.CreateValueFromExpression("threads_up_and_running", "threads_up_and_running")
+            if inferior_set_up.IsValid() and inferior_set_up.GetValueAsSigned() == 1:
+                retry = 0
+            else:
+                process.Continue()
+            retry = retry - 1
+
+        self.assertTrue(inferior_set_up.IsValid() and inferior_set_up.GetValueAsSigned() == 1, "Check that the program was able to create its threads within the allotted time")
+
+        self.check_number_of_threads(process)
+
+        main_thread = lldb.SBThread()
+        second_thread = lldb.SBThread()
+        third_thread = lldb.SBThread()
+        for idx in range(0, process.GetNumThreads()):
+            t = process.GetThreadAtIndex(idx)
+            if t.GetName() == "main thread":
+                main_thread = t
+            if t.GetName() == "second thread":
+                second_thread = t
+            if t.GetName() == "third thread":
+                third_thread = t
+
+        self.assertTrue(
+            main_thread.IsValid() and second_thread.IsValid() and third_thread.IsValid(),
+            "Got all three expected threads")
+
+        process.Kill()
+
+    def wait_for_running(self, process, listener):
+        retry_count = 5
+        if process.GetState() == lldb.eStateRunning:
+            return True
+
+        while retry_count > 0:
+            event = lldb.SBEvent()
+            listener.WaitForEvent(2, event)
+            if event.GetType() == lldb.SBProcess.eBroadcastBitStateChanged:
+                if process.GetState() == lldb.eStateRunning:
+                    return True
+            retry_count = retry_count - 1
+
+        return False
+
+    def check_number_of_threads(self, process):
+        self.assertTrue(
+            process.GetNumThreads() == 3,
+            "Check that the process has three threads when sitting at the stopper() breakpoint")
+
+
+
+    def wait_for_stop(self, process, listener):
+        retry_count = 5
+        if process.GetState() == lldb.eStateStopped or process.GetState() == lldb.eStateCrashed or process.GetState() == lldb.eStateDetached or process.GetState() == lldb.eStateExited:
+            return True
+
+        while retry_count > 0:
+            event = lldb.SBEvent()
+            listener.WaitForEvent(2, event)
+            if event.GetType() == lldb.SBProcess.eBroadcastBitStateChanged:
+                if process.GetState() == lldb.eStateStopped or process.GetState() == lldb.eStateCrashed or process.GetState() == lldb.eStateDetached or process.GetState() == lldb.eStateExited:
+                    return True
+            retry_count = retry_count - 1
+
+        return False
+
+

Added: lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/main.c?rev=289026&view=auto
==============================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/main.c (added)
+++ lldb/trunk/packages/Python/lldbsuite/test/macosx/thread-names/main.c Thu Dec  8 00:27:29 2016
@@ -0,0 +1,36 @@
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+
+int threads_up_and_running = 0;
+
+void *
+second_thread (void *in)
+{
+    pthread_setname_np ("second thread");
+    while (1) 
+        sleep (1);
+    return NULL;
+}
+
+void *
+third_thread (void *in)
+{
+    pthread_setname_np ("third thread");
+    while (1) 
+        sleep (1);
+    return NULL;
+}
+
+int main ()
+{
+    pthread_setname_np ("main thread");
+    pthread_t other_thread;
+    pthread_create (&other_thread, NULL, second_thread, NULL);
+    pthread_create (&other_thread, NULL, third_thread, NULL);
+
+    threads_up_and_running = 1;
+
+    while (1)
+        sleep (1);
+}

Modified: lldb/trunk/source/Target/Process.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Process.cpp?rev=289026&r1=289025&r2=289026&view=diff
==============================================================================
--- lldb/trunk/source/Target/Process.cpp (original)
+++ lldb/trunk/source/Target/Process.cpp Thu Dec  8 00:27:29 2016
@@ -4180,6 +4180,13 @@ void Process::ProcessEventData::DoOnRemo
   process_sp->SetPublicState(
       m_state, Process::ProcessEventData::GetRestartedFromEvent(event_ptr));
 
+  if (m_state == eStateStopped && !m_restarted) {
+    // Let process subclasses know we are about to do a public stop and
+    // do anything they might need to in order to speed up register and
+    // memory accesses.
+    process_sp->WillPublicStop();
+  }
+
   // If this is a halt event, even if the halt stopped with some reason other
   // than a plain interrupt (e.g. we had
   // already stopped for a breakpoint when the halt request came through) don't
@@ -4190,11 +4197,6 @@ void Process::ProcessEventData::DoOnRemo
 
   // If we're stopped and haven't restarted, then do the StopInfo actions here:
   if (m_state == eStateStopped && !m_restarted) {
-    // Let process subclasses know we are about to do a public stop and
-    // do anything they might need to in order to speed up register and
-    // memory accesses.
-    process_sp->WillPublicStop();
-
     ThreadList &curr_thread_list = process_sp->GetThreadList();
     uint32_t num_threads = curr_thread_list.GetSize();
     uint32_t idx;




More information about the lldb-commits mailing list