Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: tools/win/ShowThreadNames/ShowThreadNames.cc

Issue 2713773002: ShowThreadNames tool to get thread ID/name pairs in a Chrome process (Closed)
Patch Set: Add support for getting error msg. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « tools/win/ShowThreadNames/ReadMe.txt ('k') | tools/win/ShowThreadNames/ShowThreadNames.sln » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..9b4657087cfc6fa8dc1633e33f0e5f1f963f42e8
--- /dev/null
+++ b/tools/win/ShowThreadNames/ShowThreadNames.cc
@@ -0,0 +1,137 @@
+// 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);
+// Print the error message.
+void printError(TCHAR* msg);
+
+// 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
brucedawson 2017/02/23 19:33:11 binded -> bound
chengx 2017/02/23 20:45:06 Done.
+// Windows SDK, is to make it consistent with the bind of SetThreadDescription
+// in Chrome. Binding SetThreadDescription API in Chrome can only be done via
+// the system dll, rather than SDK.
brucedawson 2017/02/23 19:33:12 "can only be done by GetProcAddress, rather than t
chengx 2017/02/23 20:45:06 Done.
+typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread,
+ PWSTR* threadDescription);
+
+int main(void) {
+ unsigned int processId;
brucedawson 2017/02/23 19:33:11 Should use DWORD as type for consistency.
chengx 2017/02/23 20:45:06 Done.
+ 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);
+ if (user_input == "quit")
+ break;
+ std::cout << std::endl;
+ 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) {
+ printError(TEXT("GetThreadDescription"));
+ return (FALSE);
+ }
+
+ HANDLE threadSnap = INVALID_HANDLE_VALUE;
+ // Take a snapshot of all running threads.
+ threadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if (threadSnap == INVALID_HANDLE_VALUE) {
+ printError(TEXT("CreateToolhelp32Snapshot"));
+ return (FALSE);
+ }
+
+ THREADENTRY32 te32;
+ te32.dwSize = sizeof(THREADENTRY32);
+
+ // Retrieve information about the first thread, and exit if unsuccessful.
+ if (!Thread32First(threadSnap, &te32)) {
+ printError(TEXT("Thread32First"));
+ 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) {
+ 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);
+ name_id_map.insert(std::make_pair(data_w, te32.th32ThreadID));
brucedawson 2017/02/23 19:33:11 Don't forget to free the text with LocalFree, per
chengx 2017/02/23 20:45:06 Done.
+ } else {
+ printError(TEXT("GetThreadDescription"));
+ }
+ CloseHandle(threadHandle);
+ } else {
+ printError(TEXT("OpenThread"));
+ }
+ }
+ } 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) {
+ std::cout << it->second << "\t";
+ std::wcout << it->first << std::endl;
+ }
+
+ return (TRUE);
+}
+
+void printError(TCHAR* msg) {
+ DWORD eNum;
+ TCHAR sysMsg[256];
+ TCHAR* p;
+
+ eNum = GetLastError();
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+ NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), sysMsg,
+ 256, NULL);
+
+ // Trim the end of the line and terminate it with a null.
+ p = sysMsg;
+ while ((*p > 31) || (*p == 9))
+ ++p;
+ do {
+ *p-- = 0;
+ } while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));
+
+ // Display the message.
+ _tprintf(TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum,
+ sysMsg);
+}
brucedawson 2017/02/23 19:37:32 Put a line terminator on the last line.
chengx 2017/02/23 20:45:06 Done.
« no previous file with comments | « tools/win/ShowThreadNames/ReadMe.txt ('k') | tools/win/ShowThreadNames/ShowThreadNames.sln » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698