Have a clean(er) shutdown when detaching from a process.

llvm-svn: 249206
This commit is contained in:
Zachary Turner 2015-10-02 22:47:04 +00:00
parent a3df87b5a9
commit 6c3c0ed539
1 changed files with 19 additions and 20 deletions

View File

@ -304,20 +304,13 @@ DebuggerThread::DebugLoop()
{ {
case EXCEPTION_DEBUG_EVENT: case EXCEPTION_DEBUG_EVENT:
{ {
if (m_is_shutting_down)
{
// Don't perform any blocking operations while we're shutting down. That will
// cause TerminateProcess -> WaitForSingleObject to time out.
continue_status = DBG_EXCEPTION_NOT_HANDLED;
break;
}
ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId); ExceptionResult status = HandleExceptionEvent(dbe.u.Exception, dbe.dwThreadId);
if (status == ExceptionResult::MaskException) if (status == ExceptionResult::MaskException)
continue_status = DBG_CONTINUE; continue_status = DBG_CONTINUE;
else if (status == ExceptionResult::SendToApplication) else if (status == ExceptionResult::SendToApplication)
continue_status = DBG_EXCEPTION_NOT_HANDLED; continue_status = DBG_EXCEPTION_NOT_HANDLED;
break; break;
} }
case CREATE_THREAD_DEBUG_EVENT: case CREATE_THREAD_DEBUG_EVENT:
@ -377,6 +370,24 @@ DebuggerThread::DebugLoop()
ExceptionResult ExceptionResult
DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id) DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thread_id)
{ {
if (m_is_shutting_down)
{
// A breakpoint that occurs while `m_pid_to_detach` is non-zero is a magic exception that
// we use simply to wake up the DebuggerThread so that we can close out the debug loop.
if (m_pid_to_detach != 0 && info.ExceptionRecord.ExceptionCode == EXCEPTION_BREAKPOINT)
{
WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_PROCESS,
"Breakpoint exception is cue to detach from process 0x%x",
m_pid_to_detach);
::DebugActiveProcessStop(m_pid_to_detach);
m_detached = true;
}
// Don't perform any blocking operations while we're shutting down. That will
// cause TerminateProcess -> WaitForSingleObject to time out.
return ExceptionResult::SendToApplication;
}
bool first_chance = (info.dwFirstChance != 0); bool first_chance = (info.dwFirstChance != 0);
m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord, thread_id)); m_active_exception.reset(new ExceptionRecord(info.ExceptionRecord, thread_id));
@ -384,18 +395,6 @@ DebuggerThread::HandleExceptionEvent(const EXCEPTION_DEBUG_INFO &info, DWORD thr
"HandleExceptionEvent encountered %s chance exception 0x%x on thread 0x%x", "HandleExceptionEvent encountered %s chance exception 0x%x on thread 0x%x",
first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id); first_chance ? "first" : "second", info.ExceptionRecord.ExceptionCode, thread_id);
if (m_pid_to_detach != 0 && m_active_exception->GetExceptionCode() == EXCEPTION_BREAKPOINT) {
WINLOG_IFANY(WINDOWS_LOG_EVENT | WINDOWS_LOG_EXCEPTION | WINDOWS_LOG_PROCESS,
"Breakpoint exception is cue to detach from process 0x%x",
m_pid_to_detach);
if (::DebugActiveProcessStop(m_pid_to_detach)) {
m_detached = true;
return ExceptionResult::MaskException;
} else {
WINLOG_IFANY(WINDOWS_LOG_PROCESS, "Failed to detach, treating as a regular breakpoint");
}
}
ExceptionResult result = m_debug_delegate->OnDebugException(first_chance, ExceptionResult result = m_debug_delegate->OnDebugException(first_chance,
*m_active_exception); *m_active_exception);
m_exception_pred.SetValue(result, eBroadcastNever); m_exception_pred.SetValue(result, eBroadcastNever);