Skip to content

Commit a206a11

Browse files
Reland "[lldb] Clear thread-creation breakpoints in ProcessGDBRemote::Clear (llvm#134397)" (llvm#135296)
This reapplies commit llvm@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 `ProcessGDBRemote::Clear` was not called in that path. `Target `then proceeded to destroy its breakpoints, which resulted in a call to the destructor of a `std::vector` containing the breakpoints. Through a sequence of complicated events, destroying breakpoints caused the reference count of the underlying `ProcessGDBRemote` to finally reach zero. This, in turn, called `ProcessGDBRemote::Clear`, which attempted to destroy the breakpoints. To do that, it would go back into the Target's vector of breakpoints, 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. (cherry picked from commit c2939b9)
1 parent c4d1bcc commit a206a11

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
@@ -2486,9 +2486,18 @@ Status ProcessGDBRemote::DoDestroy() {
24862486

24872487
StopAsyncThread();
24882488
KillDebugserverProcess();
2489+
RemoveNewThreadBreakpoints();
24892490
return Status();
24902491
}
24912492

2493+
void ProcessGDBRemote::RemoveNewThreadBreakpoints() {
2494+
if (m_thread_create_bp_sp) {
2495+
if (TargetSP target_sp = m_target_wp.lock())
2496+
target_sp->RemoveBreakpointByID(m_thread_create_bp_sp->GetID());
2497+
m_thread_create_bp_sp.reset();
2498+
}
2499+
}
2500+
24922501
void ProcessGDBRemote::SetLastStopPacket(
24932502
const StringExtractorGDBRemote &response) {
24942503
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
@@ -434,6 +434,9 @@ class ProcessGDBRemote : public Process,
434434
lldb::user_id_t break_id,
435435
lldb::user_id_t break_loc_id);
436436

437+
/// Remove the breakpoints associated with thread creation from the Target.
438+
void RemoveNewThreadBreakpoints();
439+
437440
// ContinueDelegate interface
438441
void HandleAsyncStdout(llvm::StringRef out) override;
439442
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)