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

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: Add support for getting error msg. Created 3 years, 9 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 dwOwnerPID);
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 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.
25 // Windows SDK, is to make it consistent with the bind of SetThreadDescription
26 // in Chrome. Binding SetThreadDescription API in Chrome can only be done via
27 // 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.
28 typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread,
29 PWSTR* threadDescription);
30
31 int main(void) {
32 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.
33 std::string user_input;
34 while (true) {
35 std::cout
36 << "\nPlease enter the process Id, or \"quit\" to end the program : ";
37 std::getline(std::cin, user_input);
38 if (user_input == "quit")
39 break;
40 std::cout << std::endl;
41 std::stringstream ss(user_input);
42 if (ss >> processId) {
43 ListProcessThreadNames(processId);
44 } else {
45 std::cout << "input is invalid" << std::endl;
46 }
47 std::cout << std::endl;
48 }
49 return 0;
50 }
51
52 BOOL ListProcessThreadNames(DWORD dwOwnerPID) {
53 auto get_thread_description_func =
54 reinterpret_cast<GETTHREADDESCRIPTION>(::GetProcAddress(
55 ::GetModuleHandle(L"Kernel32.dll"), "GetThreadDescription"));
56
57 if (!get_thread_description_func) {
58 printError(TEXT("GetThreadDescription"));
59 return (FALSE);
60 }
61
62 HANDLE threadSnap = INVALID_HANDLE_VALUE;
63 // Take a snapshot of all running threads.
64 threadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
65 if (threadSnap == INVALID_HANDLE_VALUE) {
66 printError(TEXT("CreateToolhelp32Snapshot"));
67 return (FALSE);
68 }
69
70 THREADENTRY32 te32;
71 te32.dwSize = sizeof(THREADENTRY32);
72
73 // Retrieve information about the first thread, and exit if unsuccessful.
74 if (!Thread32First(threadSnap, &te32)) {
75 printError(TEXT("Thread32First"));
76 CloseHandle(threadSnap);
77 return (FALSE);
78 }
79
80 // Walk the thread list of the system, and display ID and name about each
81 // thread associated with the process specified.
82 std::cout << "thread_ID thread_name" << std::endl;
83 std::multimap<std::wstring, DWORD> name_id_map;
84 do {
85 if (te32.th32OwnerProcessID == dwOwnerPID) {
86 HANDLE threadHandle =
87 OpenThread(THREAD_QUERY_INFORMATION, FALSE, te32.th32ThreadID);
88 if (threadHandle) {
89 PWSTR data;
90 HRESULT hr = get_thread_description_func(threadHandle, &data);
91 if (SUCCEEDED(hr)) {
92 std::wstring data_w(data);
93 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.
94 } else {
95 printError(TEXT("GetThreadDescription"));
96 }
97 CloseHandle(threadHandle);
98 } else {
99 printError(TEXT("OpenThread"));
100 }
101 }
102 } while (Thread32Next(threadSnap, &te32));
103
104 // Clean up the snapshot object.
105 CloseHandle(threadSnap);
106
107 // Show all thread ID/name pairs.
108 for (auto it = name_id_map.begin(); it != name_id_map.end(); ++it) {
109 std::cout << it->second << "\t";
110 std::wcout << it->first << std::endl;
111 }
112
113 return (TRUE);
114 }
115
116 void printError(TCHAR* msg) {
117 DWORD eNum;
118 TCHAR sysMsg[256];
119 TCHAR* p;
120
121 eNum = GetLastError();
122 FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
123 NULL, eNum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), sysMsg,
124 256, NULL);
125
126 // Trim the end of the line and terminate it with a null.
127 p = sysMsg;
128 while ((*p > 31) || (*p == 9))
129 ++p;
130 do {
131 *p-- = 0;
132 } while ((p >= sysMsg) && ((*p == '.') || (*p < 33)));
133
134 // Display the message.
135 _tprintf(TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum,
136 sysMsg);
137 }
brucedawson 2017/02/23 19:37:32 Put a line terminator on the last line.
chengx 2017/02/23 20:45:06 Done.
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