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

Unified 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, 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
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..004e615d22bd14b6664b57b5a5bcbbbfc600d26e
--- /dev/null
+++ b/tools/win/ShowThreadNames/ShowThreadNames.cc
@@ -0,0 +1,126 @@
+// 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 threads in a process specified.
+BOOL ListProcessThreadNames(DWORD dwOwnerPID);
+
+// 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.
+typedef HRESULT(WINAPI* GETTHREADDESCRIPTION)(HANDLE hThread,
+ PWSTR* threadDescription);
+
+template <typename A, typename B>
+std::pair<B, A> flip_pair(const std::pair<A, B>& p) {
+ return std::pair<B, A>(p.second, p.first);
+}
+
+template <typename A, typename B>
+std::multimap<B, A> flip_map(const std::map<A, B>& src) {
+ std::multimap<B, A> dst;
+ std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()),
+ flip_pair<A, B>);
+ return dst;
+}
+
+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) {
+ HMODULE kernel32dll = ::GetModuleHandle(L"Kernel32.dll");
+
+ 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.
+ std::cout << "Error: cannot find Kernel32.dll" << std::endl;
+ return (FALSE);
+ }
+
+ auto get_thread_description_func = reinterpret_cast<GETTHREADDESCRIPTION>(
+ ::GetProcAddress(kernel32dll, "GetThreadDescription"));
+
+ if (!get_thread_description_func) {
+ std::cout << "GetThreadDescription API is not available in current OS"
+ << std::endl;
+ return (FALSE);
+ }
+
+ 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.
+ // Take a snapshot of all running threads
+ hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if (hThreadSnap == INVALID_HANDLE_VALUE)
+ return (FALSE);
+
+ THREADENTRY32 te32;
+ te32.dwSize = sizeof(THREADENTRY32);
+
+ // Retrieve information about the first thread, and exit if unsuccessful
+ if (!Thread32First(hThreadSnap, &te32)) {
+ std::cout << "Thread32First() call failed" << std::endl;
+ CloseHandle(hThreadSnap);
+ 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::map<DWORD, std::wstring> id_name_map;
+ do {
+ if (te32.th32OwnerProcessID == dwOwnerPID) {
+ HANDLE threadHandle =
+ 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.
+ if (threadHandle) {
+ PWSTR data;
+ HRESULT hr = get_thread_description_func(threadHandle, &data);
+ if (SUCCEEDED(hr)) {
+ std::wstring data_w(data);
+ id_name_map[te32.th32ThreadID] = data_w;
+ } else {
+ std::cout << "GetThreadDescription API call failed" << std::endl;
+ }
+ CloseHandle(threadHandle);
+ }
+ }
+ } while (Thread32Next(hThreadSnap, &te32));
+
+ // 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.
+ 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.
+
+ // show thread ID and name.
+ for (auto it = name_id_map.begin(); it != name_id_map.end(); ++it) {
+ std::cout << it->second << "\t";
+ std::wcout << it->first << std::endl;
+ }
+
+ // clean up the snapshot object.
+ 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.
+ return (TRUE);
+}

Powered by Google App Engine
This is Rietveld 408576698