-
-
Notifications
You must be signed in to change notification settings - Fork 31.4k
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
_thread.set_name(): doubt about _PYTHREAD_NAME_MAXLEN values for BSD operating systems #131268
Comments
Nice analysis. Do you want to propose a fix? |
Not yet. I am first going to expand this analysis to OpenBSD and NetBSD. |
Ok, I am done analyzing FreeBSD, OpenBSD and NetBSD. I have updated the report above to reflect my findings. In the end, I believe the fix should be: diff --git a/configure b/configure
index d0ae103014a..b0605f251a9 100755
--- a/configure
+++ b/configure
@@ -30451,10 +30451,11 @@ CPPFLAGS=$save_CPPFLAGS
case "$ac_sys_system" in
Linux*) _PYTHREAD_NAME_MAXLEN=15;; # Linux and Android
SunOS*) _PYTHREAD_NAME_MAXLEN=31;;
- NetBSD*) _PYTHREAD_NAME_MAXLEN=31;;
+ NetBSD*) _PYTHREAD_NAME_MAXLEN=15;;
Darwin) _PYTHREAD_NAME_MAXLEN=63;;
iOS) _PYTHREAD_NAME_MAXLEN=63;;
- FreeBSD*) _PYTHREAD_NAME_MAXLEN=98;;
+ FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;;
+ OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;;
*) _PYTHREAD_NAME_MAXLEN=;;
esac
if test -n "$_PYTHREAD_NAME_MAXLEN"; then
diff --git a/configure.ac b/configure.ac
index 8bb0f1c6ef4..8120ff3040b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7559,10 +7559,11 @@ _RESTORE_VAR([CPPFLAGS])
case "$ac_sys_system" in
Linux*) _PYTHREAD_NAME_MAXLEN=15;; # Linux and Android
SunOS*) _PYTHREAD_NAME_MAXLEN=31;;
- NetBSD*) _PYTHREAD_NAME_MAXLEN=31;;
+ NetBSD*) _PYTHREAD_NAME_MAXLEN=15;;
Darwin) _PYTHREAD_NAME_MAXLEN=63;;
iOS) _PYTHREAD_NAME_MAXLEN=63;;
- FreeBSD*) _PYTHREAD_NAME_MAXLEN=98;;
+ FreeBSD*) _PYTHREAD_NAME_MAXLEN=19;;
+ OpenBSD*) _PYTHREAD_NAME_MAXLEN=23;;
*) _PYTHREAD_NAME_MAXLEN=;;
esac
if test -n "$_PYTHREAD_NAME_MAXLEN"; then @vstinner What do you think? |
Adjust _PYTHREAD_NAME_MAXLEN constant on FreeBSD, NetBSD and OpenBSD. Initial patch by Xavier G. (GitHub: @xavierog).
Adjust _PYTHREAD_NAME_MAXLEN constant on FreeBSD and NetBSD; define the constant on OpenBSD. Initial patch by Xavier G. (GitHub: @xavierog).
I converted your inline patch to a pull request: #131345. |
Adjust _PYTHREAD_NAME_MAXLEN constant on FreeBSD and NetBSD. Initial patch by Xavier G.
Adjust _PYTHREAD_NAME_MAXLEN constant on FreeBSD and NetBSD. Initial patch by Xavier G.
I updated the constant on FreeBSD and NetBSD. Thanks! I discussed with @xavierog in private and he told me that the OpenBSD implementation doesn't work, so it's not worth it to update the OpenBSD constant. I close the issue. |
About the OpenBSD implementation: as this comment is being written, thread naming happens only if the |
Bug report
FreeBSD
Bug description:
6088b37 states that "FreeBSD truncates to 98 bytes silently". This figure stems from an empirical test, but I have reasons to doubt it reflects reality and believe the matter should be either fixed or clarified.
User perspective
On FreeBSD,
ps --libxo json -Ho tdname
returns a maximum of 19 characters, which matchesMAXCOMLEN
:System perspective
Let's have a look at FreeBSD's implementation of pthread_setname_np(). For the purpose of this discussion, it can be simplified down to this:
According to thr_private.h, thread->name is a simple
char *
.As to pthread_getname_np(), it boils down to:
Otherly put,
pthread_setname_np()
sets the thread name through a syscall that truncates to MAXCOMLEN=19 chars and keeps an untouched copy of it. However, that untouched copy may get truncated to the length passed topthread_getname_np()
. Here, I am tempted to say that 98-char limitation actually stems from this:cpython/Modules/_threadmodule.c
Lines 2408 to 2410 in 55815a6
Working with a 100-char array implies a 99-character string. Not sure how we get from 99 to 98, but I agree with @vstinner that:
Third perspective
Before diving into FreeBSD's libpthread implementation, I had a look at sys/procfs.h:
Although
struct thrmisc
confirms my hunch that thread names are truncated to MAXCOMLEN=19 chars, I noticed that, withinstruct prpsinfo
,PRFNAMESZ+1
+PRARGSZ+1
= 16+1 + 80+1 = 98. This was a little scary because that would imply null bytes conveniently appearing thanks to alignment (or similar shenanigans).Kernel perspective
The implementation of the thr_set_name() syscall confirms the FreeBSD kernel truncates thread names to
MAXCOMLEN
chars (specifically, it tries to copy the entire name then handlesENAMETOOLONG
).Conclusion
Although I am not 100% sure of why we got 98 instead of 99 or 100, it seems 19 would be a better choice.
OpenBSD
Bug description:
The current implementation mentions FreeBSD and NetBSD but not OpenBSD.
System perspective
The librthread implementation of pthread_set_name_np() and pthread_get_name_np() invokes the
setthrname
andgetthrname
syscalls.getthrname(2) says:
MAXCOMLEN is indeed 23:
Conclusion
configure.ac
should have an extra line:NetBSD
Bug description
The current implementation:
... is seemingly correct from the system (libpthread) perspective but it does not take the kernel perspective into account.
System perspective
The implementation of pthread_setname_np() returns
EINVAL
ifsnprintf()
reports it had to truncate the resulting name toPTHREAD_MAX_NAMELEN_NP
chars.PTHREAD_MAX_NAMELEN_NP is 32.
/usr/include/pthread.h:#define PTHREAD_MAX_NAMELEN_NP 32
pthread_setname_np() then calls _lwp_setname(), which is a syscall.
Kernel perspective
The implementation of the _lwp_setname() syscall works with a NULL-terminated MAXCOMLEN-long string.
MAXCOMLEN is 16.
/usr/include/sys/param.h:#define MAXCOMLEN 16 /* max command name remembered */
Otherly put, thread names cannot exceed 15 characters on NetBSD.
Conclusion
The correct implementation should be:
CPython versions tested on:
CPython main branch
Operating systems tested on:
Other
Linked PRs
The text was updated successfully, but these errors were encountered: