Chromium Code Reviews| Index: base/win/wait_chain.cc |
| diff --git a/base/win/wait_chain.cc b/base/win/wait_chain.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..15ec0466786dbadfef5cef3a89402907d351f551 |
| --- /dev/null |
| +++ b/base/win/wait_chain.cc |
| @@ -0,0 +1,128 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/win/wait_chain.h" |
| + |
| +#include <memory> |
| + |
| +#include "base/logging.h" |
| +#include "base/strings/stringprintf.h" |
| + |
| +namespace base { |
| +namespace win { |
| + |
| +namespace { |
| + |
| +// Helper deleter to hold a HWCT into a unique_ptr. |
| +struct WaitChainSessionDeleter { |
| + using pointer = HWCT; |
| + void operator()(HWCT session_handle) { |
|
grt (UTC plus 2)
2016/04/12 14:31:12
const methods
Patrick Monette
2016/04/12 19:13:00
Done.
|
| + ::CloseThreadWaitChainSession(session_handle); |
| + } |
| +}; |
| +using ScopedWaitChainSessionHandle = |
|
grt (UTC plus 2)
2016/04/12 14:31:12
nit: blank line before this
Patrick Monette
2016/04/12 19:13:00
Done.
|
| + std::unique_ptr<HWCT, WaitChainSessionDeleter>; |
| + |
| +const wchar_t* WctObjectTypeToString(WCT_OBJECT_TYPE type) { |
| + switch (type) { |
| + case WctCriticalSectionType: |
| + return L"CriticalSection"; |
| + case WctSendMessageType: |
| + return L"SendMessage"; |
| + case WctMutexType: |
| + return L"Mutex"; |
| + case WctAlpcType: |
| + return L"Alpc"; |
| + case WctComType: |
| + return L"Com"; |
| + case WctThreadWaitType: |
| + return L"ThreadWait"; |
| + case WctProcessWaitType: |
| + return L"ProcessWait"; |
| + case WctThreadType: |
| + return L"Thread"; |
| + case WctComActivationType: |
| + return L"ComActivation"; |
| + case WctUnknownType: |
| + return L"Unknown"; |
| + default: |
|
grt (UTC plus 2)
2016/04/12 14:31:12
can you leave off the "default" case so that there
Patrick Monette
2016/04/12 19:13:00
Done.
|
| + NOTREACHED(); |
| + return L""; |
| + } |
| +} |
| + |
| +const wchar_t* WctObjectStatusToString(WCT_OBJECT_STATUS status) { |
| + switch (status) { |
| + case WctStatusNoAccess: |
| + return L"NoAccess"; |
| + case WctStatusRunning: |
| + return L"Running"; |
| + case WctStatusBlocked: |
| + return L"Blocked"; |
| + case WctStatusPidOnly: |
| + return L"PidOnly"; |
| + case WctStatusPidOnlyRpcss: |
| + return L"PidOnlyRpcss"; |
| + case WctStatusOwned: |
| + return L"Owned"; |
| + case WctStatusNotOwned: |
| + return L"NotOwned"; |
| + case WctStatusAbandoned: |
| + return L"Abandoned"; |
| + case WctStatusUnknown: |
| + return L"Unknown"; |
| + case WctStatusError: |
| + return L"Error"; |
| + default: |
|
grt (UTC plus 2)
2016/04/12 14:31:12
same here?
Patrick Monette
2016/04/12 19:13:00
Done.
|
| + NOTREACHED(); |
| + return L""; |
| + } |
| +} |
| + |
| +} // namespace |
| + |
| +bool GetThreadWaitChain(DWORD thread_id, |
| + WaitChain* wait_chain, |
| + bool* is_deadlock) { |
| + DCHECK(wait_chain); |
| + DCHECK(is_deadlock); |
| + |
| + // Open a synchronous session. |
| + ScopedWaitChainSessionHandle session_handle( |
| + ::OpenThreadWaitChainSession(0, nullptr)); |
| + if (!session_handle) { |
| + DPLOG(ERROR) << "Failed to create the Wait Chain session"; |
| + return false; |
| + } |
| + |
| + DWORD nb_nodes = WCT_MAX_NODE_COUNT; |
| + wait_chain->resize(nb_nodes); |
| + BOOL is_cycle; |
| + if (!::GetThreadWaitChain(session_handle.get(), NULL, 0, thread_id, &nb_nodes, |
| + wait_chain->data(), &is_cycle)) { |
| + DPLOG(ERROR) << "Failed to get the thread wait chain"; |
| + return false; |
| + } |
| + |
| + *is_deadlock = is_cycle ? true : false; |
| + wait_chain->resize(nb_nodes); |
| + |
| + return true; |
| +} |
| + |
| +std::wstring WaitChainNodeToString(const WAITCHAIN_NODE_INFO& node) { |
| + if (node.ObjectType == WctThreadType) { |
| + return base::StringPrintf(L"Thread %d in process %d with status %ls", |
| + node.ThreadObject.ThreadId, |
| + node.ThreadObject.ProcessId, |
| + WctObjectStatusToString(node.ObjectStatus)); |
| + } else { |
| + return base::StringPrintf(L"Lock of type %ls with status %ls", |
| + WctObjectTypeToString(node.ObjectType), |
| + WctObjectStatusToString(node.ObjectStatus)); |
| + } |
| +} |
| + |
| +} // namespace win |
| +} // namespace base |