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

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: 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
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 threads in a process specified.
19 BOOL ListProcessThreadNames(DWORD dwOwnerPID);
20
21 // The GetThreadDescription API is available since Windows 10, version 1607.
stanisc 2017/02/23 02:29:59 Perhaps you should mention why you have to bind to
chengx 2017/02/23 03:26:04 Done.
22 typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread,
23 PWSTR* threadDescription);
24
25 template <typename A, typename B>
26 std::pair<B, A> flip_pair(const std::pair<A, B>& p) {
27 return std::pair<B, A>(p.second, p.first);
28 }
29
30 template <typename A, typename B>
31 std::multimap<B, A> flip_map(const std::map<A, B>& src) {
32 std::multimap<B, A> dst;
33 std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()),
34 flip_pair<A, B>);
35 return dst;
36 }
37
38 int main(void) {
39 unsigned int processId;
40 std::string user_input;
41 while (true) {
42 std::cout
43 << "\nPlease enter the process Id, or \"quit\" to end the program : ";
44 std::getline(std::cin, user_input);
45 std::cout << std::endl;
46 if (user_input == "quit")
47 break;
48 std::stringstream ss(user_input);
49 if (ss >> processId) {
50 ListProcessThreadNames(processId);
51 } else {
52 std::cout << "input is invalid" << std::endl;
53 }
54 std::cout << std::endl;
55 }
56 return 0;
57 }
58
59 BOOL ListProcessThreadNames(DWORD dwOwnerPID) {
60 HMODULE kernel32dll = ::GetModuleHandle(L"Kernel32.dll");
61
62 if (!kernel32dll) {
brucedawson 2017/02/23 01:57:26 I'd skip this error checking 'cause kernel32.dll w
chengx 2017/02/23 03:26:04 Done.
63 std::cout << "Error: cannot find Kernel32.dll" << std::endl;
64 return (FALSE);
65 }
66
67 auto get_thread_description_func = reinterpret_cast<GETTHREADDESCRIPTION>(
68 ::GetProcAddress(kernel32dll, "GetThreadDescription"));
69
70 if (!get_thread_description_func) {
71 std::cout << "GetThreadDescription API is not available in current OS"
72 << std::endl;
73 return (FALSE);
74 }
75
76 HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
stanisc 2017/02/23 02:29:59 I'd suggest to not use Hungarian notation i.e. han
chengx 2017/02/23 03:26:03 Changed to threadSnap.
77 // Take a snapshot of all running threads
78 hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
79 if (hThreadSnap == INVALID_HANDLE_VALUE)
80 return (FALSE);
81
82 THREADENTRY32 te32;
83 te32.dwSize = sizeof(THREADENTRY32);
84
85 // Retrieve information about the first thread, and exit if unsuccessful
86 if (!Thread32First(hThreadSnap, &te32)) {
87 std::cout << "Thread32First() call failed" << std::endl;
88 CloseHandle(hThreadSnap);
89 return (FALSE);
90 }
91
92 // Walk the thread list of the system, and display ID and name about each
93 // thread associated with the process specified.
94 std::cout << "thread_ID thread_name" << std::endl;
95 std::map<DWORD, std::wstring> id_name_map;
96 do {
97 if (te32.th32OwnerProcessID == dwOwnerPID) {
98 HANDLE threadHandle =
99 OpenThread(THREAD_ALL_ACCESS, FALSE, te32.th32ThreadID);
brucedawson 2017/02/23 01:57:26 You can probably use THREAD_QUERY_LIMITED_INFORMAT
chengx 2017/02/23 03:26:03 Done.
100 if (threadHandle) {
101 PWSTR data;
102 HRESULT hr = get_thread_description_func(threadHandle, &data);
103 if (SUCCEEDED(hr)) {
104 std::wstring data_w(data);
105 id_name_map[te32.th32ThreadID] = data_w;
106 } else {
107 std::cout << "GetThreadDescription API call failed" << std::endl;
108 }
109 CloseHandle(threadHandle);
110 }
111 }
112 } while (Thread32Next(hThreadSnap, &te32));
113
114 // reverse the map so now it is sorted by thread name.
stanisc 2017/02/23 02:29:59 Nit: comments are supposed to be complete sentence
chengx 2017/02/23 03:26:04 Done.
115 std::multimap<std::wstring, DWORD> name_id_map = flip_map(id_name_map);
brucedawson 2017/02/23 01:57:26 If you're going to put it in a multimap<wstring,DW
chengx 2017/02/23 03:26:03 I will use multimap<wstring,DWORD> directly.
116
117 // show thread ID and name.
118 for (auto it = name_id_map.begin(); it != name_id_map.end(); ++it) {
119 std::cout << it->second << "\t";
120 std::wcout << it->first << std::endl;
121 }
122
123 // clean up the snapshot object.
124 CloseHandle(hThreadSnap);
brucedawson 2017/02/23 01:57:26 For tidiness consider closing the handle as soon a
chengx 2017/02/23 03:26:04 Done.
125 return (TRUE);
126 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698