Skip to content

Commit 94e114c

Browse files
Reland "[lldb] Clear thread-creation breakpoints in ProcessGDBRemote::Clear (llvm#134397)"
This reapplies commit 232525f. The original commit triggered a sanitizer failure when Target was destroyed. In Target::Destroy, `DeleteCurrentProcess` was called, but it did not destroy the thread creation breakpoints for the underlying ProcessGDBRemote, because said method would not call `ProcessGDBRemote::Clear`. Target then proceeded to destroy its breakpoints, which resulted in a call to the destructor a std::vector containing the breakpoints. Through a sequence of complicated events, destroying breakpoints caused the reference count of the underlying to finally reach zero. This, in turn, called `ProcessGDBRemote::Clear`, which attempted to destroy the breakpoints. To do that, it would query back into the Target vector of breakpoint, which we are in the middle of destroying. We solve this by moving the breakpoint deletion into `Process:DoDestroy`, which is a virtual Process method that will be called much earlier.
1 parent e24c9e7 commit 94e114c

File tree

3 files changed

+32
-0
lines changed

3 files changed

+32
-0
lines changed

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2571,9 +2571,18 @@ Status ProcessGDBRemote::DoDestroy() {
25712571

25722572
StopAsyncThread();
25732573
KillDebugserverProcess();
2574+
CleanupNewThreadBreakpoints();
25742575
return Status();
25752576
}
25762577

2578+
void ProcessGDBRemote::CleanupNewThreadBreakpoints() {
2579+
if (m_thread_create_bp_sp) {
2580+
if (TargetSP target_sp = m_target_wp.lock())
2581+
target_sp->RemoveBreakpointByID(m_thread_create_bp_sp->GetID());
2582+
m_thread_create_bp_sp.reset();
2583+
}
2584+
}
2585+
25772586
void ProcessGDBRemote::SetLastStopPacket(
25782587
const StringExtractorGDBRemote &response) {
25792588
const bool did_exec =

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@ class ProcessGDBRemote : public Process,
436436
lldb::user_id_t break_id,
437437
lldb::user_id_t break_loc_id);
438438

439+
/// Delete breakpoints setup detecting thread creation.
440+
void CleanupNewThreadBreakpoints();
441+
439442
// ContinueDelegate interface
440443
void HandleAsyncStdout(llvm::StringRef out) override;
441444
void HandleAsyncMisc(llvm::StringRef data) override;

lldb/test/API/macosx/thread_start_bps/TestBreakpointsThreadInit.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,23 @@ def test_internal_bps_resolved(self):
3535
for bp in bps:
3636
num_resolved += bp.GetNumResolvedLocations()
3737
self.assertGreater(num_resolved, 0)
38+
39+
@skipUnlessDarwin
40+
def test_internal_bps_deleted_on_relaunch(self):
41+
self.build()
42+
43+
source_file = lldb.SBFileSpec("main.c")
44+
target, process, thread, bkpt = lldbutil.run_to_source_breakpoint(
45+
self, "initial hello", source_file
46+
)
47+
48+
self.runCmd("break list --internal")
49+
output = self.res.GetOutput()
50+
self.assertEqual(output.count("thread-creation"), 1)
51+
52+
process.Kill()
53+
self.runCmd("run", RUN_SUCCEEDED)
54+
55+
self.runCmd("break list --internal")
56+
output = self.res.GetOutput()
57+
self.assertEqual(output.count("thread-creation"), 1)

0 commit comments

Comments
 (0)