mirror of
https://github.com/intel/llvm.git
synced 2026-01-16 05:32:28 +08:00
Fix Linux bug that leaves lldb in invalid state after expression evaluation times out.
- Handle EINVAL return code from ptrace(GETSIGINFO, ...): not an error, but 'group-stop' state on Linux - propagate SIGSTOP to inferior in above case - this commit resolves the failure in expression_command/timeout testcase Thanks to Sean Callanan & Matt Kopec for helping debug this problem llvm-svn: 168523
This commit is contained in:
@@ -502,8 +502,8 @@ SingleStepOperation::Execute(ProcessMonitor *monitor)
|
||||
class SiginfoOperation : public Operation
|
||||
{
|
||||
public:
|
||||
SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
|
||||
: m_tid(tid), m_info(info), m_result(result) { }
|
||||
SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
|
||||
: m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
|
||||
|
||||
void Execute(ProcessMonitor *monitor);
|
||||
|
||||
@@ -511,6 +511,7 @@ private:
|
||||
lldb::tid_t m_tid;
|
||||
void *m_info;
|
||||
bool &m_result;
|
||||
int &m_err;
|
||||
};
|
||||
|
||||
void
|
||||
@@ -518,9 +519,10 @@ SiginfoOperation::Execute(ProcessMonitor *monitor)
|
||||
{
|
||||
struct ptrace_lwpinfo plwp;
|
||||
|
||||
if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp)))
|
||||
if (PTRACE(PT_LWPINFO, m_tid, (caddr_t)&plwp, sizeof(plwp))) {
|
||||
m_result = false;
|
||||
else {
|
||||
m_err = errno;
|
||||
} else {
|
||||
memcpy(m_info, &plwp.pl_siginfo, sizeof(siginfo_t));
|
||||
m_result = true;
|
||||
}
|
||||
@@ -1060,8 +1062,9 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
|
||||
ProcessFreeBSD *process = monitor->m_process;
|
||||
bool stop_monitoring;
|
||||
siginfo_t info;
|
||||
int ptrace_err;
|
||||
|
||||
if (!monitor->GetSignalInfo(pid, &info))
|
||||
if (!monitor->GetSignalInfo(pid, &info, ptrace_err))
|
||||
stop_monitoring = true; // pid is gone. Bail.
|
||||
else {
|
||||
switch (info.si_signo)
|
||||
@@ -1488,10 +1491,10 @@ ProcessMonitor::BringProcessIntoLimbo()
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
|
||||
ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err)
|
||||
{
|
||||
bool result;
|
||||
SiginfoOperation op(tid, siginfo, result);
|
||||
SiginfoOperation op(tid, siginfo, result, ptrace_err);
|
||||
DoOperation(&op);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public:
|
||||
/// Writes a siginfo_t structure corresponding to the given thread ID to the
|
||||
/// memory region pointed to by @p siginfo.
|
||||
bool
|
||||
GetSignalInfo(lldb::tid_t tid, void *siginfo);
|
||||
GetSignalInfo(lldb::tid_t tid, void *siginfo, int &errno);
|
||||
|
||||
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
|
||||
/// corresponding to the given thread IDto the memory pointed to by @p
|
||||
|
||||
@@ -652,8 +652,8 @@ SingleStepOperation::Execute(ProcessMonitor *monitor)
|
||||
class SiginfoOperation : public Operation
|
||||
{
|
||||
public:
|
||||
SiginfoOperation(lldb::tid_t tid, void *info, bool &result)
|
||||
: m_tid(tid), m_info(info), m_result(result) { }
|
||||
SiginfoOperation(lldb::tid_t tid, void *info, bool &result, int &ptrace_err)
|
||||
: m_tid(tid), m_info(info), m_result(result), m_err(ptrace_err) { }
|
||||
|
||||
void Execute(ProcessMonitor *monitor);
|
||||
|
||||
@@ -661,13 +661,16 @@ private:
|
||||
lldb::tid_t m_tid;
|
||||
void *m_info;
|
||||
bool &m_result;
|
||||
int &m_err;
|
||||
};
|
||||
|
||||
void
|
||||
SiginfoOperation::Execute(ProcessMonitor *monitor)
|
||||
{
|
||||
if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info))
|
||||
if (PTRACE(PTRACE_GETSIGINFO, m_tid, NULL, m_info)) {
|
||||
m_result = false;
|
||||
m_err = errno;
|
||||
}
|
||||
else
|
||||
m_result = true;
|
||||
}
|
||||
@@ -1203,9 +1206,22 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
|
||||
assert(process);
|
||||
bool stop_monitoring;
|
||||
siginfo_t info;
|
||||
int ptrace_err;
|
||||
|
||||
if (!monitor->GetSignalInfo(pid, &info))
|
||||
stop_monitoring = true; // pid is gone. Bail.
|
||||
if (!monitor->GetSignalInfo(pid, &info, ptrace_err)) {
|
||||
if (ptrace_err == EINVAL) {
|
||||
// inferior process is in 'group-stop', so deliver SIGSTOP signal
|
||||
if (!monitor->Resume(pid, SIGSTOP)) {
|
||||
assert(0 && "SIGSTOP delivery failed while in 'group-stop' state");
|
||||
}
|
||||
stop_monitoring = false;
|
||||
} else {
|
||||
// ptrace(GETSIGINFO) failed (but not due to group-stop). Most likely,
|
||||
// this means the child pid is gone (or not being debugged) therefore
|
||||
// stop the monitor thread.
|
||||
stop_monitoring = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
switch (info.si_signo)
|
||||
{
|
||||
@@ -1632,10 +1648,10 @@ ProcessMonitor::BringProcessIntoLimbo()
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo)
|
||||
ProcessMonitor::GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err)
|
||||
{
|
||||
bool result;
|
||||
SiginfoOperation op(tid, siginfo, result);
|
||||
SiginfoOperation op(tid, siginfo, result, ptrace_err);
|
||||
DoOperation(&op);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ public:
|
||||
/// Writes a siginfo_t structure corresponding to the given thread ID to the
|
||||
/// memory region pointed to by @p siginfo.
|
||||
bool
|
||||
GetSignalInfo(lldb::tid_t tid, void *siginfo);
|
||||
GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err);
|
||||
|
||||
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
|
||||
/// corresponding to the given thread IDto the memory pointed to by @p
|
||||
|
||||
Reference in New Issue
Block a user