[lldb] [gdb-remote client] Remove breakpoints throughout vfork

Temporarily remove breakpoints for the duration of vfork, in order
to prevent them from triggering in the child process.  Restore them
once the server reports that vfork has finished and it is ready to
resume execution.

Differential Revision: https://reviews.llvm.org/D100267
This commit is contained in:
Michał Górny 2021-04-11 17:16:43 +02:00
parent 4852c770fe
commit c568985845
3 changed files with 35 additions and 2 deletions

View file

@ -265,7 +265,8 @@ ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
m_waiting_for_attach(false), m_destroy_tried_resuming(false),
m_command_sp(), m_breakpoint_pc_offset(0),
m_initial_tid(LLDB_INVALID_THREAD_ID), m_replay_mode(false),
m_allow_flash_writes(false), m_erased_flash_ranges() {
m_allow_flash_writes(false), m_erased_flash_ranges(),
m_vfork_in_progress(false) {
m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
"async thread should exit");
m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
@ -5492,7 +5493,7 @@ void ProcessGDBRemote::DidForkSwitchSoftwareBreakpoints(bool enable) {
bp_site->GetType() == BreakpointSite::eExternal)) {
m_gdb_comm.SendGDBStoppointTypePacket(
eBreakpointSoftware, enable, bp_site->GetLoadAddress(),
bp_site->GetTrapOpcodeMaxByteSize(), GetInterruptTimeout());
GetSoftwareBreakpointTrapOpcode(bp_site), GetInterruptTimeout());
}
});
}
@ -5534,6 +5535,13 @@ void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {
void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
assert(!m_vfork_in_progress);
m_vfork_in_progress = true;
// Disable all software breakpoints for the duration of vfork.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
DidForkSwitchSoftwareBreakpoints(false);
LLDB_LOG(log, "Detaching forked child {0}", child_pid);
Status error = m_gdb_comm.Detach(false, child_pid);
if (error.Fail()) {
@ -5543,3 +5551,12 @@ void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) {
return;
}
}
void ProcessGDBRemote::DidVForkDone() {
assert(m_vfork_in_progress);
m_vfork_in_progress = false;
// Reenable all software breakpoints that were enabled before vfork.
if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
DidForkSwitchSoftwareBreakpoints(true);
}

View file

@ -232,6 +232,7 @@ public:
void DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) override;
void DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) override;
void DidVForkDone() override;
protected:
friend class ThreadGDBRemote;
@ -296,6 +297,8 @@ protected:
using FlashRange = FlashRangeVector::Entry;
FlashRangeVector m_erased_flash_ranges;
bool m_vfork_in_progress;
// Accessors
bool IsRunning(lldb::StateType state) {
return state == lldb::eStateRunning || IsStepping(state);

View file

@ -0,0 +1,13 @@
# REQUIRES: native
# UNSUPPORTED: system-darwin
# UNSUPPORTED: system-windows
# RUN: %clangxx_host %p/Inputs/fork.cpp -DTEST_FORK=vfork -o %t
# RUN: %lldb -b -s %s %t | FileCheck %s
b parent_func
b child_func
process launch
# CHECK-NOT: function run in parent
# CHECK: stop reason = breakpoint
continue
# CHECK: function run in parent
# CHECK: child exited: 0