forked from OSchip/llvm-project
[Windows, Process] Fix an issue in windows thread handling that was causing LLDB to hang
Summary: The function ResumeThread on Windows returns a DWORD which is an unsigned int. In TargetThreadWindows::DoResume, there's code that determines how many times to call ResumeThread based on whether the return value is greater than 0. Since the function returns -1 (as an unsigned int) on failure, this was getting stuck in an infinite loop if ResumeThread failed for any reason. The correct thing to do is check whether the return value is -1 and then return the appropriate error instead of ignoring the return value. Reviewers: asmith, zturner, labath Reviewed By: zturner Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D47020 llvm-svn: 332670
This commit is contained in:
parent
3c4c8a0937
commit
0fd67b537b
|
@ -349,13 +349,23 @@ Status ProcessWindows::DoResume() {
|
|||
|
||||
LLDB_LOG(log, "resuming {0} threads.", m_thread_list.GetSize());
|
||||
|
||||
bool failed = false;
|
||||
for (uint32_t i = 0; i < m_thread_list.GetSize(); ++i) {
|
||||
auto thread = std::static_pointer_cast<TargetThreadWindows>(
|
||||
m_thread_list.GetThreadAtIndex(i));
|
||||
thread->DoResume();
|
||||
Status result = thread->DoResume();
|
||||
if (result.Fail()) {
|
||||
failed = true;
|
||||
LLDB_LOG(log, "Trying to resume thread at index {0}, but failed with error {1}.", i, result);
|
||||
}
|
||||
}
|
||||
|
||||
SetPrivateState(eStateRunning);
|
||||
if (failed) {
|
||||
error.SetErrorString("ProcessWindows::DoResume failed");
|
||||
return error;
|
||||
} else {
|
||||
SetPrivateState(eStateRunning);
|
||||
}
|
||||
} else {
|
||||
LLDB_LOG(log, "error: process %I64u is in state %u. Returning...",
|
||||
m_session_data->m_debugger->GetProcess().GetProcessId(),
|
||||
|
|
|
@ -98,11 +98,11 @@ Unwind *TargetThreadWindows::GetUnwinder() {
|
|||
return m_unwinder_ap.get();
|
||||
}
|
||||
|
||||
bool TargetThreadWindows::DoResume() {
|
||||
Status TargetThreadWindows::DoResume() {
|
||||
StateType resume_state = GetTemporaryResumeState();
|
||||
StateType current_state = GetState();
|
||||
if (resume_state == current_state)
|
||||
return true;
|
||||
return Status();
|
||||
|
||||
if (resume_state == eStateStepping) {
|
||||
uint32_t flags_index =
|
||||
|
@ -118,8 +118,16 @@ bool TargetThreadWindows::DoResume() {
|
|||
DWORD previous_suspend_count = 0;
|
||||
HANDLE thread_handle = m_host_thread.GetNativeThread().GetSystemHandle();
|
||||
do {
|
||||
// ResumeThread returns -1 on error, or the thread's *previous* suspend count on success.
|
||||
// This means that the return value is 1 when the thread was restarted.
|
||||
// Note that DWORD is an unsigned int, so we need to explicitly compare with -1.
|
||||
previous_suspend_count = ::ResumeThread(thread_handle);
|
||||
} while (previous_suspend_count > 0);
|
||||
|
||||
if (previous_suspend_count == (DWORD)-1)
|
||||
return Status(::GetLastError(), eErrorTypeWin32);
|
||||
|
||||
} while (previous_suspend_count > 1);
|
||||
}
|
||||
return true;
|
||||
|
||||
return Status();
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
bool CalculateStopInfo() override;
|
||||
Unwind *GetUnwinder() override;
|
||||
|
||||
bool DoResume();
|
||||
Status DoResume();
|
||||
|
||||
HostThread GetHostThread() const { return m_host_thread; }
|
||||
|
||||
|
|
Loading…
Reference in New Issue