aboutsummaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp')
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp111
1 files changed, 65 insertions, 46 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 4bc5711..3d87150 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -447,13 +447,7 @@ void NativeProcessLinux::MonitorCallback(NativeThreadLinux &thread,
// This is a thread that exited. Ensure we're not tracking it anymore.
StopTrackingThread(thread);
- if (is_main_thread) {
- // The main thread exited. We're done monitoring. Report to delegate.
- SetExitStatus(status, true);
-
- // Notify delegate that our process has exited.
- SetState(StateType::eStateExited, true);
- }
+ assert(!is_main_thread && "Main thread exits handled elsewhere");
return;
}
@@ -611,6 +605,13 @@ void NativeProcessLinux::MonitorSIGTRAP(const siginfo_t &info,
}
ResumeThread(thread, state, LLDB_INVALID_SIGNAL_NUMBER);
+ if (is_main_thread) {
+ // Main thread report the read (WIFEXITED) event only after all threads in
+ // the process exit, so we need to stop tracking it here instead of in
+ // MonitorCallback
+ StopTrackingThread(thread);
+ }
+
break;
}
@@ -1177,11 +1178,11 @@ Status NativeProcessLinux::PopulateMemoryRegionCache() {
// Linux kernel since 2.6.14 has /proc/{pid}/smaps
// if CONFIG_PROC_PAGE_MONITOR is enabled
- auto BufferOrError = getProcFile(GetID(), "smaps");
+ auto BufferOrError = getProcFile(GetID(), GetCurrentThreadID(), "smaps");
if (BufferOrError)
ParseLinuxSMapRegions(BufferOrError.get()->getBuffer(), callback);
else {
- BufferOrError = getProcFile(GetID(), "maps");
+ BufferOrError = getProcFile(GetID(), GetCurrentThreadID(), "maps");
if (!BufferOrError) {
m_supports_mem_region = LazyBool::eLazyBoolNo;
return BufferOrError.getError();
@@ -1232,7 +1233,7 @@ NativeProcessLinux::Syscall(llvm::ArrayRef<uint64_t> args) {
addr_t exe_addr = region_it->first.GetRange().GetRangeBase();
- NativeThreadLinux &thread = *GetThreadByID(GetID());
+ NativeThreadLinux &thread = *GetCurrentThread();
assert(thread.GetState() == eStateStopped);
NativeRegisterContextLinux &reg_ctx = thread.GetRegisterContext();
@@ -1384,8 +1385,9 @@ Status NativeProcessLinux::ReadMemoryTags(int32_t type, lldb::addr_t addr,
tags_iovec.iov_len = num_tags;
Status error = NativeProcessLinux::PtraceWrapper(
- details->ptrace_read_req, GetID(), reinterpret_cast<void *>(read_addr),
- static_cast<void *>(&tags_iovec), 0, nullptr);
+ details->ptrace_read_req, GetCurrentThreadID(),
+ reinterpret_cast<void *>(read_addr), static_cast<void *>(&tags_iovec),
+ 0, nullptr);
if (error.Fail()) {
// Discard partial reads
@@ -1453,7 +1455,7 @@ Status NativeProcessLinux::WriteMemoryTags(int32_t type, lldb::addr_t addr,
tags_vec.iov_len = num_tags;
Status error = NativeProcessLinux::PtraceWrapper(
- details->ptrace_write_req, GetID(),
+ details->ptrace_write_req, GetCurrentThreadID(),
reinterpret_cast<void *>(write_addr), static_cast<void *>(&tags_vec), 0,
nullptr);
@@ -1525,15 +1527,14 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
// The process_vm_readv path is about 50 times faster than ptrace api. We
// want to use this syscall if it is supported.
- const ::pid_t pid = GetID();
-
struct iovec local_iov, remote_iov;
local_iov.iov_base = buf;
local_iov.iov_len = size;
remote_iov.iov_base = reinterpret_cast<void *>(addr);
remote_iov.iov_len = size;
- bytes_read = process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0);
+ bytes_read = process_vm_readv(GetCurrentThreadID(), &local_iov, 1,
+ &remote_iov, 1, 0);
const bool success = bytes_read == size;
Log *log = GetLog(POSIXLog::Process);
@@ -1557,7 +1558,7 @@ Status NativeProcessLinux::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
for (bytes_read = 0; bytes_read < size; bytes_read += remainder) {
Status error = NativeProcessLinux::PtraceWrapper(
- PTRACE_PEEKDATA, GetID(), (void *)addr, nullptr, 0, &data);
+ PTRACE_PEEKDATA, GetCurrentThreadID(), (void *)addr, nullptr, 0, &data);
if (error.Fail())
return error;
@@ -1592,8 +1593,8 @@ Status NativeProcessLinux::WriteMemory(lldb::addr_t addr, const void *buf,
memcpy(&data, src, k_ptrace_word_size);
LLDB_LOG(log, "[{0:x}]:{1:x}", addr, data);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_POKEDATA, GetID(),
- (void *)addr, (void *)data);
+ error = NativeProcessLinux::PtraceWrapper(
+ PTRACE_POKEDATA, GetCurrentThreadID(), (void *)addr, (void *)data);
if (error.Fail())
return error;
} else {
@@ -1857,46 +1858,64 @@ void NativeProcessLinux::ThreadWasCreated(NativeThreadLinux &thread) {
}
}
+static llvm::Optional<WaitStatus> HandlePid(::pid_t pid) {
+ Log *log = GetLog(POSIXLog::Process);
+
+ int status;
+ ::pid_t wait_pid = llvm::sys::RetryAfterSignal(
+ -1, ::waitpid, pid, &status, __WALL | __WNOTHREAD | WNOHANG);
+
+ if (wait_pid == 0)
+ return llvm::None;
+
+ if (wait_pid == -1) {
+ Status error(errno, eErrorTypePOSIX);
+ LLDB_LOG(log, "waitpid({0}, &status, _) failed: {1}", pid,
+ error);
+ return llvm::None;
+ }
+
+ assert(wait_pid == pid);
+
+ WaitStatus wait_status = WaitStatus::Decode(status);
+
+ LLDB_LOG(log, "waitpid({0}) got status = {1}", pid, wait_status);
+ return wait_status;
+}
+
void NativeProcessLinux::SigchldHandler() {
Log *log = GetLog(POSIXLog::Process);
// Threads can appear or disappear as a result of event processing, so gather
// the events upfront.
llvm::DenseMap<lldb::tid_t, WaitStatus> tid_events;
+ bool checked_main_thread = false;
for (const auto &thread_up : m_threads) {
- int status = -1;
- ::pid_t wait_pid =
- llvm::sys::RetryAfterSignal(-1, ::waitpid, thread_up->GetID(), &status,
- __WALL | __WNOTHREAD | WNOHANG);
-
- if (wait_pid == 0)
- continue; // Nothing to do for this thread.
-
- if (wait_pid == -1) {
- Status error(errno, eErrorTypePOSIX);
- LLDB_LOG(log, "waitpid({0}, &status, _) failed: {1}", thread_up->GetID(),
- error);
- continue;
- }
+ if (thread_up->GetID() == GetID())
+ checked_main_thread = true;
- assert(wait_pid == static_cast<::pid_t>(thread_up->GetID()));
-
- WaitStatus wait_status = WaitStatus::Decode(status);
-
- LLDB_LOG(log, "waitpid({0}) got status = {1}", thread_up->GetID(),
- wait_status);
- tid_events.try_emplace(thread_up->GetID(), wait_status);
+ if (llvm::Optional<WaitStatus> status = HandlePid(thread_up->GetID()))
+ tid_events.try_emplace(thread_up->GetID(), *status);
+ }
+ // Check the main thread even when we're not tracking it as process exit
+ // events are reported that way.
+ if (!checked_main_thread) {
+ if (llvm::Optional<WaitStatus> status = HandlePid(GetID()))
+ tid_events.try_emplace(GetID(), *status);
}
for (auto &KV : tid_events) {
LLDB_LOG(log, "processing {0}({1}) ...", KV.first, KV.second);
- NativeThreadLinux *thread = GetThreadByID(KV.first);
- if (thread) {
- MonitorCallback(*thread, KV.second);
- } else {
- // This can happen if one of the events is an main thread exit.
- LLDB_LOG(log, "... but the thread has disappeared");
+ if (KV.first == GetID() && (KV.second.type == WaitStatus::Exit ||
+ KV.second.type == WaitStatus::Signal)) {
+
+ // The process exited. We're done monitoring. Report to delegate.
+ SetExitStatus(KV.second, true);
+ return;
}
+ NativeThreadLinux *thread = GetThreadByID(KV.first);
+ assert(thread && "Why did this thread disappear?");
+ MonitorCallback(*thread, KV.second);
}
}