Author: Ted Woodward
Date: 2021-09-15T18:09:32-05:00
New Revision: 17589538aaef2b5ae27a0bfeb4346aff433aa59d

URL: 
https://github.com/llvm/llvm-project/commit/17589538aaef2b5ae27a0bfeb4346aff433aa59d
DIFF: 
https://github.com/llvm/llvm-project/commit/17589538aaef2b5ae27a0bfeb4346aff433aa59d.diff

LOG: [lldb-vscode] Fix focus thread when previous thread exits

The thread that Visual Studio Code displays on a stop is called the focus 
thread. When the previous focus thread exits and we stop in a new thread, 
lldb-vscode does not tell vscode to set the new thread as the focus thread, so 
it selects the first thread in the thread list.

This patch changes lldb-vscode to tell vscode that the new thread is the focus 
thread. It also includes a test that verifies the DAP stop message for this 
case contains the correct values.

Reviewed By: clayborg, wallace

Differential Revision: https://reviews.llvm.org/D109633

Added: 
    lldb/test/API/tools/lldb-vscode/correct-thread/Makefile
    lldb/test/API/tools/lldb-vscode/correct-thread/TestVSCode_correct_thread.py
    lldb/test/API/tools/lldb-vscode/correct-thread/main.c

Modified: 
    lldb/tools/lldb-vscode/lldb-vscode.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/test/API/tools/lldb-vscode/correct-thread/Makefile 
b/lldb/test/API/tools/lldb-vscode/correct-thread/Makefile
new file mode 100644
index 0000000000000..121868fa8ec33
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/correct-thread/Makefile
@@ -0,0 +1,4 @@
+C_SOURCES := main.c
+CFLAGS_EXTRAS := -lpthread
+
+include Makefile.rules

diff  --git 
a/lldb/test/API/tools/lldb-vscode/correct-thread/TestVSCode_correct_thread.py 
b/lldb/test/API/tools/lldb-vscode/correct-thread/TestVSCode_correct_thread.py
new file mode 100644
index 0000000000000..4b7b03745692e
--- /dev/null
+++ 
b/lldb/test/API/tools/lldb-vscode/correct-thread/TestVSCode_correct_thread.py
@@ -0,0 +1,47 @@
+"""
+Test lldb-vscode setBreakpoints request
+"""
+
+from __future__ import print_function
+
+import unittest2
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+
+
+class TestVSCode_correct_thread(lldbvscode_testcase.VSCodeTestCaseBase):
+
+    mydir = TestBase.compute_mydir(__file__)
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_correct_thread(self):
+        '''
+            Tests that the correct thread is selected if we continue from
+            a thread that goes away and hit a breakpoint in another thread.
+            In this case, the selected thread should be the thread that
+            just hit the breakpoint, and not the first thread in the list.
+        '''
+        program = self.getBuildArtifact("a.out")
+        self.build_and_launch(program)
+        source = 'main.c'
+        breakpoint_line = line_number(source, '// break here')
+        lines = [breakpoint_line]
+        # Set breakpoint in the thread function
+        breakpoint_ids = self.set_source_breakpoints(source, lines)
+        self.assertEqual(len(breakpoint_ids), len(lines),
+                        "expect correct number of breakpoints")
+        self.continue_to_breakpoints(breakpoint_ids)
+        # We're now stopped at the breakpoint in the first thread, thread #2.
+        # Continue to join the first thread and hit the breakpoint in the
+        # second thread, thread #3.
+        self.vscode.request_continue()
+        stopped_event = self.vscode.wait_for_stopped()
+        # Verify that the description is the relevant breakpoint,
+        # preserveFocusHint is False and threadCausedFocus is True
+        
self.assertTrue(stopped_event[0]['body']['description'].startswith('breakpoint 
%s.' % breakpoint_ids[0]))
+        self.assertFalse(stopped_event[0]['body']['preserveFocusHint'])
+        self.assertTrue(stopped_event[0]['body']['threadCausedFocus'])

diff  --git a/lldb/test/API/tools/lldb-vscode/correct-thread/main.c 
b/lldb/test/API/tools/lldb-vscode/correct-thread/main.c
new file mode 100644
index 0000000000000..157c3f994db1e
--- /dev/null
+++ b/lldb/test/API/tools/lldb-vscode/correct-thread/main.c
@@ -0,0 +1,23 @@
+#include <pthread.h>
+#include <stdio.h>
+
+int state_var;
+
+void *thread (void *in)
+{
+  state_var++; // break here
+  return NULL;
+}
+
+int main(int argc, char **argv)
+{
+  pthread_t t1, t2;
+
+  pthread_create(&t1, NULL, *thread, NULL);
+  pthread_join(t1, NULL);
+  pthread_create(&t2, NULL, *thread, NULL);
+  pthread_join(t2, NULL);
+
+  printf("state_var is %d\n", state_var);
+  return 0;
+}

diff  --git a/lldb/tools/lldb-vscode/lldb-vscode.cpp 
b/lldb/tools/lldb-vscode/lldb-vscode.cpp
index 59d8debe6378c..5c237c00deabe 100644
--- a/lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ b/lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -232,13 +232,17 @@ void SendThreadStoppedEvent() {
       // set it as the focus thread if below if needed.
       lldb::tid_t first_tid_with_reason = LLDB_INVALID_THREAD_ID;
       uint32_t num_threads_with_reason = 0;
+      bool focus_thread_exists = false;
       for (uint32_t thread_idx = 0; thread_idx < num_threads; ++thread_idx) {
         lldb::SBThread thread = process.GetThreadAtIndex(thread_idx);
         const lldb::tid_t tid = thread.GetThreadID();
         const bool has_reason = ThreadHasStopReason(thread);
         // If the focus thread doesn't have a stop reason, clear the thread ID
-        if (tid == g_vsc.focus_tid && !has_reason)
-          g_vsc.focus_tid = LLDB_INVALID_THREAD_ID;
+        if (tid == g_vsc.focus_tid) {
+          focus_thread_exists = true;
+          if (!has_reason)
+            g_vsc.focus_tid = LLDB_INVALID_THREAD_ID;
+        }
         if (has_reason) {
           ++num_threads_with_reason;
           if (first_tid_with_reason == LLDB_INVALID_THREAD_ID)
@@ -246,10 +250,10 @@ void SendThreadStoppedEvent() {
         }
       }
 
-      // We will have cleared g_vsc.focus_tid if he focus thread doesn't
-      // have a stop reason, so if it was cleared, or wasn't set, then set the
-      // focus thread to the first thread with a stop reason.
-      if (g_vsc.focus_tid == LLDB_INVALID_THREAD_ID)
+      // We will have cleared g_vsc.focus_tid if he focus thread doesn't have
+      // a stop reason, so if it was cleared, or wasn't set, or doesn't exist,
+      // then set the focus thread to the first thread with a stop reason.
+      if (!focus_thread_exists || g_vsc.focus_tid == LLDB_INVALID_THREAD_ID)
         g_vsc.focus_tid = first_tid_with_reason;
 
       // If no threads stopped with a reason, then report the first one so


        
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to