forked from OSchip/llvm-project
[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
This commit is contained in:
parent
37a5a3ae55
commit
17589538aa
|
@ -0,0 +1,4 @@
|
|||
C_SOURCES := main.c
|
||||
CFLAGS_EXTRAS := -lpthread
|
||||
|
||||
include Makefile.rules
|
|
@ -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'])
|
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue