Skip to content

Commit c7f50e6

Browse files
committed
Refactor to SEIZE->SIGSTOP->INTERRUPT
1 parent 4583570 commit c7f50e6

File tree

2 files changed

+29
-110
lines changed

2 files changed

+29
-110
lines changed

lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp

Lines changed: 29 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -312,26 +312,10 @@ NativeProcessLinux::Manager::Attach(
312312
Log *log = GetLog(POSIXLog::Process);
313313
LLDB_LOG(log, "pid = {0:x}", pid);
314314

315-
// This safety check lets us decide if we should
316-
// seize or attach.
317-
ProcessInstanceInfo process_info;
318-
if (!Host::GetProcessInfo(pid, process_info))
319-
return llvm::make_error<StringError>("Unable to read process info",
320-
llvm::inconvertibleErrorCode());
321-
322-
std::vector<::pid_t> tids;
323-
// IsCoreDumping is an optional, so check for value then true/false.
324-
if (process_info.IsCoreDumping() && *process_info.IsCoreDumping()) {
325-
auto attached_or = NativeProcessLinux::Seize(pid);
326-
if (!attached_or)
327-
return attached_or.takeError();
328-
tids = std::move(*attached_or);
329-
} else {
330-
auto attached_or = NativeProcessLinux::Attach(pid);
331-
if (!attached_or)
332-
return attached_or.takeError();
333-
tids = std::move(*attached_or);
334-
}
315+
auto tids_or = NativeProcessLinux::Attach(pid);
316+
if (!tids_or)
317+
return tids_or.takeError();
318+
ArrayRef<::pid_t> tids = *tids_or;
335319

336320
llvm::Expected<ArchSpec> arch_or =
337321
NativeRegisterContextLinux::DetermineArchitecture(tids[0]);
@@ -461,91 +445,10 @@ NativeProcessLinux::NativeProcessLinux(::pid_t pid, int terminal_fd,
461445
SetState(StateType::eStateStopped, false);
462446
}
463447

464-
llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Seize(::pid_t pid) {
465-
Log *log = GetLog(POSIXLog::Process);
466-
467-
uint64_t options = GetDefaultPtraceOpts();
468-
Status status;
469-
// Use a map to keep track of the threads which we have attached/need to
470-
// attach.
471-
Host::TidMap tids_to_attach;
472-
while (Host::FindProcessThreads(pid, tids_to_attach)) {
473-
for (Host::TidMap::iterator it = tids_to_attach.begin();
474-
it != tids_to_attach.end();) {
475-
if (it->second == true) {
476-
continue;
477-
}
478-
lldb::tid_t tid = it->first;
479-
if ((status = PtraceWrapper(PTRACE_SEIZE, tid, nullptr, (void *)options))
480-
.Fail()) {
481-
// No such thread. The thread may have exited. More error handling
482-
// may be needed.
483-
if (status.GetError() == ESRCH) {
484-
it = tids_to_attach.erase(it);
485-
continue;
486-
}
487-
if (status.GetError() == EPERM) {
488-
// Depending on the value of ptrace_scope, we can return a
489-
// different error that suggests how to fix it.
490-
return AddPtraceScopeNote(status.ToError());
491-
}
492-
return status.ToError();
493-
}
494-
495-
if ((status = PtraceWrapper(PTRACE_INTERRUPT, tid)).Fail()) {
496-
// No such thread. The thread may have exited. More error handling
497-
// may be needed.
498-
if (status.GetError() == ESRCH) {
499-
it = tids_to_attach.erase(it);
500-
continue;
501-
}
502-
if (status.GetError() == EPERM) {
503-
// Depending on the value of ptrace_scope, we can return a
504-
// different error that suggests how to fix it.
505-
return AddPtraceScopeNote(status.ToError());
506-
}
507-
return status.ToError();
508-
}
509-
510-
int wpid =
511-
llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL);
512-
// Need to use __WALL otherwise we receive an error with errno=ECHLD At
513-
// this point we should have a thread stopped if waitpid succeeds.
514-
if (wpid < 0) {
515-
// No such thread. The thread may have exited. More error handling
516-
// may be needed.
517-
if (errno == ESRCH) {
518-
it = tids_to_attach.erase(it);
519-
continue;
520-
}
521-
return llvm::errorCodeToError(
522-
std::error_code(errno, std::generic_category()));
523-
}
524-
525-
LLDB_LOG(log, "adding tid = {0}", tid);
526-
it->second = true;
527-
528-
// move the loop forward
529-
++it;
530-
}
531-
}
532-
533-
size_t tid_count = tids_to_attach.size();
534-
if (tid_count == 0)
535-
return llvm::make_error<StringError>("No such process",
536-
llvm::inconvertibleErrorCode());
537-
538-
std::vector<::pid_t> tids;
539-
tids.reserve(tid_count);
540-
for (const auto &p : tids_to_attach)
541-
tids.push_back(p.first);
542-
543-
return std::move(tids);
544-
}
545-
546448
llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
547449
Log *log = GetLog(POSIXLog::Process);
548450

451+
uint64_t options = GetDefaultPtraceOpts();
549452
Status status;
550453
// Use a map to keep track of the threads which we have attached/need to
551454
// attach.
@@ -556,9 +459,12 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
556459
if (it->second == false) {
557460
lldb::tid_t tid = it->first;
558461

559-
// Attach to the requested process.
560-
// An attach will cause the thread to stop with a SIGSTOP.
561-
if ((status = PtraceWrapper(PTRACE_ATTACH, tid)).Fail()) {
462+
// Seize and interrupt the requested process.
463+
// This will cause the thread to stop in a TRACE_STOP state.
464+
// Akin to a sigstop but without sending the signal.
465+
if ((status =
466+
PtraceWrapper(PTRACE_SEIZE, tid, nullptr, (void *)options))
467+
.Fail()) {
562468
// No such thread. The thread may have exited. More error handling
563469
// may be needed.
564470
if (status.GetError() == ESRCH) {
@@ -573,6 +479,24 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
573479
return status.ToError();
574480
}
575481

482+
// Send a sigstop, this makes it so our seize->interrupt is signal wise
483+
// the same as ptrace_attach. We do this so any program/workflow
484+
// depending on the sending of a sigstop will still receive a sigstop.
485+
tgkill(tid, tid, SIGSTOP);
486+
487+
if ((status = PtraceWrapper(PTRACE_INTERRUPT, tid)).Fail()) {
488+
// No such thread, the thread may have exited, this shouldn't
489+
// happen at this stage, but we check regardless
490+
if (status.GetError() == ESRCH) {
491+
it = tids_to_attach.erase(it);
492+
continue;
493+
}
494+
495+
// No check for EPERM because we already checked for it above
496+
// when we seized
497+
return status.ToError();
498+
}
499+
576500
int wpid =
577501
llvm::sys::RetryAfterSignal(-1, ::waitpid, tid, nullptr, __WALL);
578502
// Need to use __WALL otherwise we receive an error with errno=ECHLD At
@@ -588,9 +512,6 @@ llvm::Expected<std::vector<::pid_t>> NativeProcessLinux::Attach(::pid_t pid) {
588512
std::error_code(errno, std::generic_category()));
589513
}
590514

591-
if ((status = SetDefaultPtraceOpts(tid)).Fail())
592-
return status.ToError();
593-
594515
LLDB_LOG(log, "adding tid = {0}", tid);
595516
it->second = true;
596517
}

lldb/source/Plugins/Process/Linux/NativeProcessLinux.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,6 @@ class NativeProcessLinux : public NativeProcessELF,
190190

191191
// Returns a list of process threads that we have attached to.
192192
static llvm::Expected<std::vector<::pid_t>> Attach(::pid_t pid);
193-
// Returns a list of process threads that we have seized and interrupted.
194-
static llvm::Expected<std::vector<::pid_t>> Seize(::pid_t pid);
195193

196194
static Status SetDefaultPtraceOpts(const lldb::pid_t);
197195

0 commit comments

Comments
 (0)