Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.Thread.getName/setName: rework windows implementation #10003

Merged
merged 3 commits into from
Feb 15, 2022

Conversation

0x08088405
Copy link
Contributor

@0x08088405 0x08088405 commented Oct 22, 2021

So, the current implementation of Thread.getName and Thread.setName on Win32 uses the GetThreadDescription and SetThreadDescription APIs respectively. The problem with this is sort of documented in the source:

zig/lib/std/Thread.zig

Lines 88 to 93 in a3c9bfe

.windows => if (target.os.isAtLeast(.windows, .win10_rs1)) |res| {
// SetThreadDescription is only available since version 1607, which is 10.0.14393.795
// See https://en.wikipedia.org/wiki/Microsoft_Windows_SDK
if (!res) {
return error.Unsupported;
}

However, it hard links to kernel32.dll and the function was not in there until after W10 1607, it was previously acquired by querying the symbol from kernelbase.dll at runtime. Putting loader code for a shared object in the standard library is pretty ugly though, and doesn't solve properly linking to it in cases where it's available. Thankfully as with a lot of things in Win32 you can ditch this terrible null-terminator-using API entirely, and just use Nt* functions to get the job done correctly.

This PR changes the functions to use the Nt(Get/Set)InformationThread APIs to query and set the name, and since the higher level APIs are just a wrapper for these, it's fully compatible with them, sans extra allocation for query, global error code set, and the need to check for compatibility at all because on older systems it simply just returns a status saying it's not implemented. Great!

Note: These don't have anything to do with the new implementation, these were present in the previous one too, but if you do setName("") then getName() returns null because NT makes no distinction between an unset thread name and an empty thread name. The other problem is if that someone else uses Nt* functions to make a thread name bigger than the current limit in std, it'll yield error.Unexpected, or potentially cause a very ugly assertion failure in utf16leToUtf8 even (unsure), the limit on the thread name is 64KiB (c_ushort), not 32B like it currently says. Maybe something related to these issues should be put in this PR too, but it could be out of scope, especially since the latter only happens if raw Win32 (or FFI) is mixed with std.

lib/std/os/windows.zig Show resolved Hide resolved
lib/std/os/windows/ntdll.zig Outdated Show resolved Hide resolved
I've seen having this be wrong break some cross-compilers, and it's
also how it is in other files so it's best to be consistent.

It's also just the actual casing of the file.
@0x08088405
Copy link
Contributor Author

0x08088405 commented Jan 15, 2022

Looks like other changes caused a merge conflict, so I've reapplied the changes on top of master, and did c_void -> anyopaque.

@0x08088405
Copy link
Contributor Author

Quickly checked to see what the Windows CI is about (I assumed it was the usual at the time) and noticed that the rebased version did not actually work anymore, it was due to the control flow being slightly restructured inbetween those commits. The fix was just:

diff --git a/lib/std/Thread.zig b/lib/std/Thread.zig
index 6ddc6dd75..05f6fd66d 100644
--- a/lib/std/Thread.zig
+++ b/lib/std/Thread.zig
@@ -104,7 +104,7 @@ pub fn setName(self: Thread, name: []const u8) SetNameError!void {
                 &unicode_string,
                 @sizeOf(os.windows.UNICODE_STRING),
             )) {
-                .SUCCESS => {},
+                .SUCCESS => return,
                 .NOT_IMPLEMENTED => return error.Unsupported,
                 else => |err| return os.windows.unexpectedStatus(err),
             }

@Vexu Vexu merged commit cf5009f into ziglang:master Feb 15, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants