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); |
+} |