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

Side by Side Diff: tools/win/ShowThreadNames/ShowThreadNames.cc

Issue 2713773002: ShowThreadNames tool to get thread ID/name pairs in a Chrome process (Closed)
Patch Set: Fix nits. 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 unified diff | Download patch
« no previous file with comments | « tools/win/ShowThreadNames/ReadMe.txt ('k') | tools/win/ShowThreadNames/ShowThreadNames.sln » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <windows.h>
6
7 #include <stdio.h>
8 #include <tchar.h>
9 #include <tlhelp32.h>
10
11 #include <algorithm>
12 #include <iostream>
13 #include <iterator>
14 #include <map>
15 #include <sstream>
16 #include <string>
17
18 // List all thread names in a process specified.
19 BOOL ListProcessThreadNames(DWORD owner_pid);
20 // Print the error message.
21 void printError(TCHAR* msg);
22
23 // The GetThreadDescription API is available since Windows 10, version 1607.
24 // The reason why this API is bound in this way rather than just using the
25 // Windows SDK, is that this API isn't yet available in the SDK that Chrome
26 // builds with.
27 // Binding SetThreadDescription API in Chrome can only be done by
28 // GetProcAddress, rather than the import library.
29 typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread,
30 PWSTR* threadDescription);
31
32 int main(void) {
33 DWORD process_Id;
34 std::string user_input;
35 while (true) {
36 std::cout
37 << "\nPlease enter the process Id, or \"quit\" to end the program : ";
38 std::getline(std::cin, user_input);
39 // Convert the user input to lower case.
40 std::transform(user_input.begin(), user_input.end(), user_input.begin(),
41 ::tolower);
42 if (user_input == "quit")
43 break;
44 std::cout << std::endl;
45 std::stringstream ss(user_input);
46 if (ss >> process_Id) {
47 ListProcessThreadNames(process_Id);
48 } else {
49 std::cout << "Input is invalid" << std::endl;
50 }
51 std::cout << std::endl;
52 }
53 return 0;
54 }
55
56 BOOL ListProcessThreadNames(DWORD owner_pid) {
57 auto get_thread_description_func =
58 reinterpret_cast<GETTHREADDESCRIPTION>(::GetProcAddress(
59 ::GetModuleHandle(L"Kernel32.dll"), "GetThreadDescription"));
60
61 if (!get_thread_description_func) {
62 printError(TEXT("GetThreadDescription"));
63 return (FALSE);
64 }
65
66 HANDLE thread_snapshot = INVALID_HANDLE_VALUE;
67 // Take a snapshot of all running threads.
68 thread_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
69 if (thread_snapshot == INVALID_HANDLE_VALUE) {
70 printError(TEXT("CreateToolhelp32Snapshot"));
71 return (FALSE);
72 }
73
74 THREADENTRY32 te32;
75 te32.dwSize = sizeof(THREADENTRY32);
76
77 // Retrieve information about the first thread, and exit if unsuccessful.
78 if (!Thread32First(thread_snapshot, &te32)) {
79 printError(TEXT("Thread32First"));
80 CloseHandle(thread_snapshot);
81 return (FALSE);
82 }
83
84 // Walk the thread list of the system, and display ID and name about each
85 // thread associated with the process specified.
86 std::cout << "thread_ID thread_name" << std::endl;
87 std::multimap<std::wstring, DWORD> name_id_map;
88 do {
89 if (te32.th32OwnerProcessID == owner_pid) {
90 HANDLE thread_handle =
91 OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID);
92 if (thread_handle) {
93 PWSTR data;
94 HRESULT hr = get_thread_description_func(thread_handle, &data);
95 if (SUCCEEDED(hr)) {
96 std::wstring thread_name(data);
97 LocalFree(data);
98 name_id_map.insert(std::make_pair(thread_name, te32.th32ThreadID));
99 } else {
100 printError(TEXT("GetThreadDescription"));
101 }
102 CloseHandle(thread_handle);
103 } else {
104 printError(TEXT("OpenThread"));
105 }
106 }
107 } while (Thread32Next(thread_snapshot, &te32));
108
109 // Clean up the snapshot object.
110 CloseHandle(thread_snapshot);
111
112 // Show all thread ID/name pairs.
113 for (auto name_id_pair : name_id_map) {
114 std::cout << name_id_pair.second << "\t";
115 std::wcout << name_id_pair.first << std::endl;
116 }
117
118 return (TRUE);
119 }
120
121 void printError(TCHAR* msg) {
122 DWORD eNum;
123 TCHAR sysMsg[256];
124 TCHAR* p;
125
126 eNum = GetLastError();
127 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
128 NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), sysMsg,
129 256, NULL);
130
131 // Trim the end of the line and terminate it with a null.
132 p = sysMsg;
133 while ((*p > 31) || (*p == 9))
134 ++p;
135 do {
136 *p-- = 0;
137 } while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));
138
139 // Display the message.
140 _tprintf(TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum,
141 sysMsg);
142 }
OLDNEW
« 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