Skip to content
Permalink
Browse files
8238649: Call new Win32 API SetThreadDescription in os::set_native_th…
…read_name

Co-authored-by: Markus GaisBauer <markus.gaisbauer@dynatrace.com>
Reviewed-by: stuefe, luhenry
  • Loading branch information
David Holmes and quijote committed Jun 15, 2021
1 parent 2e70bc3 commit 9f3c7e74ff00a7550742ed8b9d6671c2d4bb6041
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 1 deletion.
@@ -885,8 +885,62 @@ uint os::processor_id() {
return (uint)GetCurrentProcessorNumber();
}

// For dynamic lookup of SetThreadDescription API
typedef HRESULT (WINAPI *SetThreadDescriptionFnPtr)(HANDLE, PCWSTR);
typedef HRESULT (WINAPI *GetThreadDescriptionFnPtr)(HANDLE, PWSTR*);
static SetThreadDescriptionFnPtr _SetThreadDescription = NULL;
DEBUG_ONLY(static GetThreadDescriptionFnPtr _GetThreadDescription = NULL;)

// forward decl.
errno_t convert_to_unicode(char const* char_path, LPWSTR* unicode_path);

void os::set_native_thread_name(const char *name) {

// From Windows 10 and Windows 2016 server, we have a direct API
// for setting the thread name/description:
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreaddescription

if (_SetThreadDescription != NULL) {
// SetThreadDescription takes a PCWSTR but we have conversion routines that produce
// LPWSTR. The only difference is that PCWSTR is a pointer to const WCHAR.
LPWSTR unicode_name;
errno_t err = convert_to_unicode(name, &unicode_name);
if (err == ERROR_SUCCESS) {
HANDLE current = GetCurrentThread();
HRESULT hr = _SetThreadDescription(current, unicode_name);
if (FAILED(hr)) {
log_debug(os, thread)("set_native_thread_name: SetThreadDescription failed - falling back to debugger method");
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
} else {
log_trace(os, thread)("set_native_thread_name: SetThreadDescription succeeded - new name: %s", name);

#ifdef ASSERT
// For verification purposes in a debug build we read the thread name back and check it.
PWSTR thread_name;
HRESULT hr2 = _GetThreadDescription(current, &thread_name);
if (FAILED(hr2)) {
log_debug(os, thread)("set_native_thread_name: GetThreadDescription failed!");
} else {
int res = CompareStringW(LOCALE_USER_DEFAULT,
0, // no special comparison rules
unicode_name,
-1, // null-terminated
thread_name,
-1 // null-terminated
);
assert(res == CSTR_EQUAL,
"Name strings were not the same - set: %ls, but read: %ls", unicode_name, thread_name);
LocalFree(thread_name);
}
#endif
FREE_C_HEAP_ARRAY(WCHAR, unicode_name);
return;
}
} else {
log_debug(os, thread)("set_native_thread_name: convert_to_unicode failed - falling back to debugger method");
}
}

// See: http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
//
// Note that unfortunately this only works if the process
@@ -895,6 +949,7 @@ void os::set_native_thread_name(const char *name) {

// If there is no debugger attached skip raising the exception
if (!IsDebuggerPresent()) {
log_debug(os, thread)("set_native_thread_name: no debugger present so unable to set thread name");
return;
}

@@ -4193,6 +4248,7 @@ extern "C" {

static jint initSock();


// this is called _after_ the global arguments have been parsed
jint os::init_2(void) {

@@ -4311,6 +4367,24 @@ jint os::init_2(void) {
jdk_misc_signal_init();
}

// Lookup SetThreadDescription - the docs state we must use runtime-linking of
// kernelbase.dll, so that is what we do.
HINSTANCE _kernelbase = LoadLibrary(TEXT("kernelbase.dll"));
if (_kernelbase != NULL) {
_SetThreadDescription =
reinterpret_cast<SetThreadDescriptionFnPtr>(
GetProcAddress(_kernelbase,
"SetThreadDescription"));
#ifdef ASSERT
_GetThreadDescription =
reinterpret_cast<GetThreadDescriptionFnPtr>(
GetProcAddress(_kernelbase,
"GetThreadDescription"));
#endif
}
log_info(os, thread)("The SetThreadDescription API is%s available.", _SetThreadDescription == NULL ? " not" : "");


return JNI_OK;
}

@@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception {
pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread=debug", "-version");
output = new OutputAnalyzer(pb.start());
analyzeOutputForDebugLevel(output);

output.reportDiagnosticSummary();
}

}

1 comment on commit 9f3c7e7

@openjdk-notifier
Copy link

@openjdk-notifier openjdk-notifier bot commented on 9f3c7e7 Jun 15, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.