How to map pthread_t to pid (on Linux)
Asked Answered
M

3

10

Is there a sane way to map a pthread_t value (as returned from pthread_create() or std::thread::native_hanle() ) to pid(tid) in Linux? Before someone gets duplicate-happy, this is not about finding thread's own pid (which can be done with gettid()).

The insane way would be to somehow compel a thread to call gettid() and pass along the result, but that's way too much trouble.

One of the possible applications I have in mind is to reconcile threads created within program (where pthread_t is available) with output provided by ps -T.

Megalomania answered 14/12, 2017 at 15:39 Comment(8)
As far as I know, in linux, pthread_t is a pointer to struct pthread, which has a tid member. But I don't know any acceptable way to read this information. If you have debug symbols available, you can check this struct out in gdb with ptype pthread. For debug purposes only, you can read the offset of tid with p &((pthread*)0)->tid, then use this offset in the program itself to read tid from pthread_t. Or you can use read the offset from the symbol file itself with some dwarf reader library, to be "portable".Teen
@Teen very interesting indeed, thanks for this information!Megalomania
it depends on the underneath implementation of threads. linuxthreads might have process ids associated with them, getpid should return it. posix threads might not, so getpid will return pid of the main process. check this: https://mcmap.net/q/828878/-understanding-pthreadsStokehole
Couple of dupes exhibit A exhibit BEyas
@n.m. you answer provides a nice diversity from 'you can't do it since pthreads are not Linux threads' as a consensus non-answer.Megalomania
Well this is a hack, pthreads are not supposed to be mappable to OS tids, but abstractions leak.Eyas
@n.m. sure thing. Abstractions are nice, but than again, sometimes you just have to go to OS level to map to OS-provided tools. And there is an accepted way of doing so through _np suffix. Shame it doesn't exist for thread ids.Megalomania
It's not actually too hard to do the "insane" part. sigaction + pthread_sigqueue + a function* (or std::function*) in info->si_value.sival_ptr + condition variable = building block for a generic blocking executeOnThread(id, func) implementation. You can then use use that to build parameterized versions of gettid and any other thread dependent functions (such as backtrace, getrusage, etc.) that you are interested in. If you also use C++, then lambdas and variable capture help smooth over the passing of params in and out, but that's just for convenience, you can obviously do an equivalent in C.Steddman
E
5

One (convoluted, non-portable, Linux-specific, lightly destructive) method of mapping pthread_t to tid without looking into struct pthread is as follows:

  1. Use pthread_setname_np to set a thread name to something unique.
  2. Iterate over subdirectories of /proc/self/task and read a line from a file named comm in each of those.
  3. If the line equals to the unique string just used, extract tid from the last component of the subdirectory name. This is your answer.

The thread name is not used by the OS for anything, so it should be safe to change it. Nevertheless you probably want to set it back to the value it had originally (use pthread_getname_np to obtain it).

Eyas answered 27/12, 2017 at 19:12 Comment(2)
As a matter of fact, my threads already have names, so this approach is certainly worth considering. Accepting.Megalomania
@SergeyA, can you share how did you achieve your goal using pthread_setname_np?Pupillary
E
1

A somewhat hacky way of doing this on Linux would be with the process_vm_readv system call. If you know the pthread_t, use it to copy the memory over from the remote process to a local buffer, then cast the pointer to a struct pthread and retrieve the value of the tid field.

Eryn answered 14/3, 2021 at 21:31 Comment(0)
B
-1

Pthreads are POSIX Threads. In pthread_t is a typedef to some type of long depending on your architecture. It is actually a pointer typecasted to an internal struct pthread as mentioned here above.

It is on purpose that the struct pthread is not returned. Threading is highly dependent on the underlying OS. Threads are not implemented equally on all Unix flavored OS'es. I don't believe even that gettid is a POSIX function, I believe it is Linux specific.

You can have a look at the glibc/nptl source code for linux specific implementation of struct pthread See https://sourceware.org/git/?p=glibc.git;a=blob;f=nptl/descr.h;h=fdeb397eab94730a5dab3181abcdae815ed6914e;hb=48a8f8328122ab8d06b7333cb87be46feeaf7cca

But I believe what you are looking for is getpid. It is the process id and not thread id

Bolin answered 27/12, 2017 at 17:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.