Chromium Code Reviews| Index: tools/win/ShowThreadNames/ShowThreadNames.cc |
| diff --git a/tools/win/ShowThreadNames/ShowThreadNames.cc b/tools/win/ShowThreadNames/ShowThreadNames.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1627ede5800d8a7e9ee8cce50e73c8be735347ab |
| --- /dev/null |
| +++ b/tools/win/ShowThreadNames/ShowThreadNames.cc |
| @@ -0,0 +1,109 @@ |
| +// Copyright (c) 2017 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 <windows.h> |
| + |
| +#include <stdio.h> |
| +#include <tchar.h> |
| +#include <tlhelp32.h> |
| + |
| +#include <algorithm> |
| +#include <iostream> |
| +#include <iterator> |
| +#include <map> |
| +#include <sstream> |
| +#include <string> |
| + |
| +// List all thread names in a process specified. |
| +BOOL ListProcessThreadNames(DWORD dwOwnerPID); |
| + |
| +// The GetThreadDescription API is available since Windows 10, version 1607. |
| +// The reason why this API is binded in this way rather than just using the |
| +// Windows SDK, is to make it consistent with the bind of SetThreadDescription |
| +// in Chrome. Binding SetThreadDescription API in Chrome can only be done via |
|
stanisc
2017/02/23 19:19:44
You could just say that this API isn't yet availab
chengx
2017/02/23 20:45:06
Done.
|
| +// the system dll, rather than SDK. |
| +typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread, |
| + PWSTR* threadDescription); |
| + |
| +int main(void) { |
| + unsigned int processId; |
| + std::string user_input; |
| + while (true) { |
| + std::cout |
| + << "\nPlease enter the process Id, or \"quit\" to end the program : "; |
| + std::getline(std::cin, user_input); |
| + std::cout << std::endl; |
| + if (user_input == "quit") |
| + break; |
| + std::stringstream ss(user_input); |
| + if (ss >> processId) { |
| + ListProcessThreadNames(processId); |
| + } else { |
| + std::cout << "input is invalid" << std::endl; |
| + } |
| + std::cout << std::endl; |
| + } |
| + return 0; |
| +} |
| + |
| +BOOL ListProcessThreadNames(DWORD dwOwnerPID) { |
| + auto get_thread_description_func = |
| + reinterpret_cast<GETTHREADDESCRIPTION>(::GetProcAddress( |
| + ::GetModuleHandle(L"Kernel32.dll"), "GetThreadDescription")); |
| + |
| + if (!get_thread_description_func) { |
| + std::cout << "GetThreadDescription API is not available in current OS" |
| + << std::endl; |
| + return (FALSE); |
| + } |
| + |
| + HANDLE threadSnap = INVALID_HANDLE_VALUE; |
|
stanisc
2017/02/23 19:19:44
How about thread_snapshot?
chengx
2017/02/23 20:45:06
Done.
|
| + // Take a snapshot of all running threads. |
| + threadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); |
| + if (threadSnap == INVALID_HANDLE_VALUE) |
| + return (FALSE); |
| + |
| + THREADENTRY32 te32; |
| + te32.dwSize = sizeof(THREADENTRY32); |
| + |
| + // Retrieve information about the first thread, and exit if unsuccessful. |
| + if (!Thread32First(threadSnap, &te32)) { |
| + std::cout << "Thread32First() call failed" << std::endl; |
| + CloseHandle(threadSnap); |
| + return (FALSE); |
| + } |
| + |
| + // Walk the thread list of the system, and display ID and name about each |
| + // thread associated with the process specified. |
| + std::cout << "thread_ID thread_name" << std::endl; |
| + std::multimap<std::wstring, DWORD> name_id_map; |
| + do { |
| + if (te32.th32OwnerProcessID == dwOwnerPID) { |
|
stanisc
2017/02/23 19:19:44
Use chrome code naming convention for this as well
chengx
2017/02/23 20:45:06
Done.
|
| + HANDLE threadHandle = |
| + OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID); |
| + if (threadHandle) { |
| + PWSTR data; |
| + HRESULT hr = get_thread_description_func(threadHandle, &data); |
| + if (SUCCEEDED(hr)) { |
| + std::wstring data_w(data); |
|
stanisc
2017/02/23 19:19:44
Could you use a more descriptive name such as thre
chengx
2017/02/23 20:45:06
Done.
|
| + name_id_map.insert(std::make_pair(data_w, te32.th32ThreadID)); |
| + } else { |
| + std::cout << "GetThreadDescription API call failed" << std::endl; |
| + } |
| + CloseHandle(threadHandle); |
| + } |
| + } |
| + } while (Thread32Next(threadSnap, &te32)); |
| + |
| + // Clean up the snapshot object. |
| + CloseHandle(threadSnap); |
| + |
| + // Show all thread ID/name pairs. |
| + for (auto it = name_id_map.begin(); it != name_id_map.end(); ++it) { |
|
stanisc
2017/02/23 19:19:44
Nit: you could use C++ 11 foreach loop here - for
chengx
2017/02/23 20:45:06
Done.
|
| + std::cout << it->second << "\t"; |
| + std::wcout << it->first << std::endl; |
| + } |
| + |
| + return (TRUE); |
| +} |