-
-
Notifications
You must be signed in to change notification settings - Fork 55
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
fix _pthread_tid_offset check for older versions of glibc #95
Conversation
For recent versions of glic, the pthread struct is like, { ... pid_t tid, // size_of(pid_t) == 4 pid_t pid_unused, // value is 0 ... } Before this commit, the _pthread_tid_offset check logic iterates the memory block in every 8 bytes (uintptr_t), and it works because pid_unused is 0. However, in older versions of glibc like 2.17 which is used by RHEL/Centos 7, its pthread struct is like below and comparing 8 bytes it does not match the tid because the pid field is non-zero. { ... pid_t tid, // sizeof(pid_t) == 4 pid_t pid, // value is not 0 but pid ... }
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.
Ah! So this is due to memory alignment. Thanks for debugging this, good catch! 👍 Just a comment, otherwise LGTM!
log_d("pthread_t at %p", py_thread->tid); | ||
if (py_thread->raddr.pid == (uintptr_t) _pthread_buffer[i]) { | ||
if (py_thread->raddr.pid == *((pid_t *) _pthread_buffer + i)) { |
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 would prefer if we did this as a fallback in case steps of size uniptr_t
are failing. My concern is that this might end up accidentally matching something else. WDYT?
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 think if we use that as a fallback, that does not really protect you from accidentally matching something else, as it if the comparing uintptr_t fails, it would fallback to the comparing pid_t logic..
Do you think if it good we parse the output of gnu_get_libc_version(), as we can surely know from which glibc version it started to replace pid with pid_unused. So for glibc versions above that we compare uintptr_t, for lower glibc versions we compare pid_t.
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.
Do you think if it good we parse the output of gnu_get_libc_version()
This sounds good to me. Can we make it so that it is also compatible with musl as I'd like to start making these builds available too from releases? We should be able to import features.h
with both glibc and musl, and check for __GLIBC__
and __GLIBC_MINOR__
(which en passant might save us from having to parse the string returned by gnu_get_libc_version
?).
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.
hmm I think the macro resolves to a fixed version at compile time, so the built binary is not portable. but the function could work at runtime. I will need to furthur check though.
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.
hmm I think the macro resolves to a fixed version at compile time
Ah, of course! We're not linking libc statically so indeed we'd have to call the function. But at least we should be able to use the macros to determine what we're compiling against 🤞.
Closing this for now. Should this still be a problem we can have another look at it. |
Requirements for Adding, Changing, Fixing or Removing a Feature
This fixes #93
For recent versions of glic, the pthread struct is like,
Before this commit, the _pthread_tid_offset check logic iterates the memory
block in every 8 bytes (uintptr_t), and it works because pid_unused is 0.
However, in older versions of glibc like 2.17 which is used by RHEL/Centos 7,
its pthread struct is like below and comparing 8 bytes it does not match
the tid because the pid field is non-zero.
Description of the Change
Instead of iterating the memory block in uintptr_t size that is 8 bytes on 64bit Linux, iterate in pid_t size that should be 4 bytes.
Verification Process
Tested on both a Debian 11 host and a RHEL7 host.