forked from OSchip/llvm-project
[lldb-server] Reset stop reason of all threads when resuming
Summary: This patch makes the stop reason reset logic similar to MacOS' debugserver, where exceptions are reset for all threads when resuming process for stepping or continuing (see [[96f3ea0d21/lldb/tools/debugserver/source/MacOSX/MachThreadList.cpp (L433)
| MachThreadList::ProcessWillResume ]] and [[96f3ea0d21/lldb/tools/debugserver/source/MacOSX/MachThread.cpp (L363)
| MachThread::ThreadWillResume ]]). Resetting stop reasons on resume fixes problems where LLDB spuriously reports SIGTRAP signal stop reason for deleted breakpoints (both internal and public) and where LLDB stops on an internal breakpoint while stepping over while a breakpoint is hit in another thread. See [[ https://bugs.llvm.org/show_bug.cgi?id=45642 | PR45642 ]] for details. Reviewed By: jingham, labath Differential Revision: https://reviews.llvm.org/D79308
This commit is contained in:
parent
51446c13f6
commit
56de738d18
|
@ -1062,6 +1062,8 @@ Status NativeProcessLinux::Resume(const ResumeActionList &resume_actions) {
|
|||
if (action == nullptr) {
|
||||
LLDB_LOG(log, "no action specified for pid {0} tid {1}", GetID(),
|
||||
thread->GetID());
|
||||
// Make sure we reset the stop reason for all the threads.
|
||||
static_cast<NativeThreadLinux &>(*thread).ResetStopReason();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -396,7 +396,10 @@ void NativeThreadLinux::SetStoppedByTrace() {
|
|||
|
||||
void NativeThreadLinux::SetStoppedWithNoReason() {
|
||||
SetStopped();
|
||||
ResetStopReason();
|
||||
}
|
||||
|
||||
void NativeThreadLinux::ResetStopReason() {
|
||||
m_stop_info.reason = StopReason::eStopReasonNone;
|
||||
m_stop_info.details.signal.signo = 0;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,8 @@ private:
|
|||
|
||||
void SetStopped();
|
||||
|
||||
void ResetStopReason();
|
||||
|
||||
// Member Variables
|
||||
lldb::StateType m_state;
|
||||
ThreadStopInfo m_stop_info;
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
CXX_SOURCES := main.cpp
|
||||
ENABLE_THREADS := YES
|
||||
|
||||
include Makefile.rules
|
|
@ -0,0 +1,63 @@
|
|||
"""
|
||||
Test stop reasons after hitting and deleting a breakpoint and
|
||||
stepping another thread. Scenario:
|
||||
- run a thread
|
||||
- stop the thread at a breakpoint
|
||||
- delete the breakpoint
|
||||
- single step on the main thread
|
||||
The thread stopped at the deleted breakpoint should have stop reason
|
||||
'none'.
|
||||
"""
|
||||
|
||||
|
||||
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class ThreadBreakStepOtherTestCase(TestBase):
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
|
||||
def test_hit_breakpoint_delete_step_other_thread(self):
|
||||
main_source_file = lldb.SBFileSpec("main.cpp")
|
||||
self.build()
|
||||
(target, process, main_thread, _) = lldbutil.run_to_source_breakpoint(
|
||||
self, "// main break here", main_source_file, only_one_thread = False)
|
||||
|
||||
# Run until the breakpoint in the thread.
|
||||
thread_breakpoint = target.BreakpointCreateBySourceRegex(
|
||||
"// thread break here", main_source_file)
|
||||
self.assertGreater(
|
||||
thread_breakpoint.GetNumLocations(),
|
||||
0,
|
||||
"thread breakpoint has no locations associated with it.")
|
||||
process.Continue()
|
||||
stopped_threads = lldbutil.get_threads_stopped_at_breakpoint(
|
||||
process, thread_breakpoint)
|
||||
self.assertEquals(
|
||||
1,
|
||||
len(stopped_threads),
|
||||
"only one thread expected stopped at the thread breakpoint")
|
||||
breakpoint_thread = stopped_threads[0]
|
||||
|
||||
# Delete the breakpint in the thread and do a step in the main thread.
|
||||
target.BreakpointDelete(thread_breakpoint.GetID())
|
||||
main_thread.StepInstruction(False)
|
||||
|
||||
# Check the stop reasons.
|
||||
reason = main_thread.GetStopReason()
|
||||
self.assertEqual(
|
||||
lldb.eStopReasonPlanComplete,
|
||||
reason,
|
||||
"Expected thread stop reason 'plancomplete', but got '%s'" %
|
||||
lldbutil.stop_reason_to_str(reason))
|
||||
|
||||
reason = breakpoint_thread.GetStopReason()
|
||||
self.assertEqual(
|
||||
lldb.eStopReasonNone,
|
||||
reason,
|
||||
"Expected thread stop reason 'none', but got '%s'" %
|
||||
lldbutil.stop_reason_to_str(reason))
|
|
@ -0,0 +1,27 @@
|
|||
#include <thread>
|
||||
#include "pseudo_barrier.h"
|
||||
|
||||
// Barrier for starting the thread and reaching the loop in main.
|
||||
pseudo_barrier_t g_barrier;
|
||||
volatile int g_foo = 0;
|
||||
|
||||
void thread_func() {
|
||||
// Wait until all the threads are running
|
||||
pseudo_barrier_wait(g_barrier);
|
||||
g_foo = 1; // thread break here
|
||||
}
|
||||
|
||||
int main() {
|
||||
g_foo = 0; // main break here
|
||||
|
||||
pseudo_barrier_init(g_barrier, 2);
|
||||
std::thread t(thread_func);
|
||||
pseudo_barrier_wait(g_barrier);
|
||||
|
||||
// A dummy loop to have something to step through.
|
||||
volatile int i = 0;
|
||||
while (g_foo == 0)
|
||||
++i;
|
||||
t.join();
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue