-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
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
gh-59705: Implement _thread.set_name() on Windows #128675
Conversation
Implement set_name() with SetThreadDescription() and _get_name() with GetThreadDescription(). If SetThreadDescription() or GetThreadDescription() is not available in kernelbase.dll, delete the method when the _thread module is imported. Truncate the thread name to an arbitrary limit of 64 characters. set_name() raises ValueError if the name contains an embedded null character. Co-authored-by: Eryk Sun <[email protected]>
Code based on @eryksun's code: #59705 (comment). Differences with his code:
I copied this limit from @eryksun's code. Maybe it can be extended to 32766 characters?
If it's a blocker issue, I can write the code differently to truncate to the first null character instead. |
I misunderstood the code, in fact, the name is truncated at the first null character (ValueError is not raised): same behavior than Linux/macOS/FreeBSD/etc. |
The alternative to The Process Explorer tool doesn't show thread names. |
I'm not familiar with Windows API, but this looks right to me. A review from @python/windows-team would be great though :) (Specifically: this is a best-effort attempt to add info to aid debugging or understanding what's going on in a system: we want to as much as we reasonably can to the OS, but it's OK drop part of the name or not set it at all, and errors should be discarded since the user didn't really ask for this. And |
I plan to merge this change at the beginning of next week (January 20th). |
I fixed the truncation for surrogate pairs and I added tests with non-BMP characters (creating surrogate pairs on Windows). |
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.
I am not a Windows expert, but the code LGTM. Although I am not sure that we should set such small artificial limit.
There are also some issues in tests.
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.
LGTM.
Ok, I increased the limit from 64 to 32766 characters. |
Thanks for the reviews. I enabled auto-merge. |
@@ -2594,6 +2648,31 @@ thread_module_exec(PyObject *module) | |||
} | |||
#endif | |||
|
|||
#ifdef MS_WINDOWS | |||
HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll"); | |||
if (kernelbase != NULL) { |
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.
If this check fails, we likely want to report a system error since everything is broken, but at least we should call DelAttr
to remove the functions, since the function pointers will be null.
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.
set_name()
/_get_name()
is a minor feature of the _thread
module, I would prefer to not prevent to import _thread
if loading kernelbase.dll
fails for whatever reason.
but at least we should call DelAttr to remove the functions, since the function pointers will be null.
Oops, my code was wrong. Fixed.
PC/pyconfig.h.in
Outdated
@@ -753,4 +753,8 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ | |||
/* Define if libssl has X509_VERIFY_PARAM_set1_host and related function */ | |||
#define HAVE_X509_VERIFY_PARAM_SET1_HOST 1 | |||
|
|||
// Truncate the thread name to 64 characters. The OS limit is 32766 wide | |||
// characters, but long names aren't of practical use. | |||
#define PYTHREAD_NAME_MAXLEN 64 |
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.
There's no reason for us to artificially limit this at all, but I'd rather be much closer to the real limit than this. "Aren't of practical use" is a value judgement, not a technical limit.
Also, there's no C API for this, so we probably don't need a public C constant for the limit.
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.
I changed the limit to 32766 characters.
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.
Also, there's no C API for this, so we probably don't need a public C constant for the limit.
I can rename the macro use _Py
prefix. But that unrelated to the Windows implementation, so I would prefer to do it in a separated change. Non-Windows platforms use the same macro.
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.
Also, there's no C API for this, so we probably don't need a public C constant for the limit.
I created #128945 to make the macro private.
Remove the module methods if GetModuleHandleW() fails.
@zooba: Please review the updated PR. I fixed |
LGTM |
Merged. Thanks for reviews. |
Implement set_name() with SetThreadDescription() and _get_name() with GetThreadDescription(). If SetThreadDescription() or GetThreadDescription() is not available in kernelbase.dll, delete the method when the _thread module is imported.
Truncate the thread name to 32766 characters.
set_name() raises ValueError if the name contains an embedded null character.