-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Implement named threads on Windows #41736
Conversation
Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @alexcrichton (or someone else) soon. If any changes to this PR are deemed necessary, please add them as extra commits. This ensures that the reviewer can see what has changed since they last reviewed the code. Due to the way GitHub handles out-of-date commits, this should also make it reasonably obvious what issues have or haven't been addressed. Large or tricky changes may require several passes of review and changes. Please see the contribution instructions for more information. |
Hang on, this is broken on 32-bit. I'll fix it tomorrow. |
The stack overflow handler is not always guaranteed to be registered, for example cdylibs that are loaded and invoked from other languages. It would perhaps be better to have a separate handler for this that is lazily registered when you set the name. |
Good point @retep998, I've moved it to a separate handler. 32-bit is still broken, I think the |
Perhaps the 32-bit definition could manually fill in padding/packing/etc? |
I just tested the struct from the example using VC++ and as far as I can tell the |
src/libstd/sys/windows/thread.rs
Outdated
mem::size_of::<c::ULONG_PTR>()) as c::DWORD; | ||
|
||
unsafe { | ||
c::RaiseException(c::MS_VC_EXCEPTION, 0, size, mem::transmute(&info)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please don't use transmute. You can safely cast raw pointers &info as *const _ as *const _
.
32-bit is now working 🎉 The struct packing was actually fine, the problem was caused by a pre-existing bug. |
Whoa nice catch @jsheard! It looks like there's a few other locations in the codebase that define |
Awesome thanks @jsheard and thanks with the implementation! Want to squash commits and I'll r+? |
I just realized there's a serious bug in my original approach. The magic 0x406D1388 exception code is not reserved for passing messages to the debugger, so if some linked non-Rust code happens to use 0x406D1388 for some other purpose the global filter would silently eat their exceptions. With 2^32 possible exception codes this is unlikely to happen but that's no excuse 😓 I've pushed a different implementation that should be more robust. Does this look sensible? |
It looks like it now ignores all exceptions instead of specifically that exception code? If only Rust exposed a way to catch SEH exceptions the way you can in Microsoft C... |
It does ignore all exceptions if That said it might be more efficient to check the code anyway and early-return if it isn't |
From the documentation vectored handlers:
Accessing TLS, however, will on Windows possibly allocate memory and acquire synchronization objects, so using TLS here may not play out so well :( |
Argh, I'm out of ideas. Perhaps we should just abandon the magic exception and focus on SetThreadDescription. It has the downside of only working on Windows 10 and literally no tools actually support it yet (not even Visual Studio), but time will solve that problem eventually. |
I'd personally be ok with the original implementation, it seems like another excepting colliding with this one is exceedingly rare because it'd break anyone attempting to set the name of a thread like this, right? |
@alexcrichton most programs wouldn't set a thread name like this, in C or C++ you would use Microsoft's SEH language extension to catch the exception in a scoped block like this: __try {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} __except (EXCEPTION_CONTINUE_EXECUTION) {} This is easy and safe, but impossible to express in pure Rust so we're in the unique position of trying to use program-wide VEH callbacks without causing any side effects in the rest of the program. I'm tempted to give up and just implement SetThreadDescription, it turns out that Windows Performance Analyzer supports it now so we have something to test with. Still waiting for support in MSVC though. |
If you're feeling intrepid you could actually implement that in Rust! I could help you out poking around in the compiler if you'd like. This'd basically just surface itself as a new intrinsic that's MSVC specific and also specific to the standard library. I'm not 100% sure how much work it would take, though. I believe LLVM is capable of producing the code to match the semantics of that block, so we'd just need to harness it. |
I'm sure it's possible, but it would be an insane amount of work and complexity just to implement this one trivial feature. IMO there's no practical and 100% safe way to implement this via the exception. I'll return to this when debuggers start using the new |
Ok that's also fine by me, thanks regardless for the PR @jsheard! |
@alexcrichton @jsheard any interest in reviving this by using SetThreadDescription now that Win10 is much more common? I could try to do this if @jsheard is busy. It will need to use |
Already did! It's been merged for a while now: #44374 |
Sweet! Thank you!
… |
Adds support for named threads on Windows, using the very awkward convention supported by most debuggers.