How can I get the whole thread name when I use `ps -T -p [pid]`
The thread name length is restricted to 16 characters (including the terminating null byte \0
). If the length, including the \0
, exceeds 16 bytes, the string is silently truncated before storing it.
See pthread_setname_np
and proc.5
-> find /proc/[pid]/task/[tid]/comm
.
Related:
How to get the full executable name of a running process in Linux
Name of running threads inside a process
As hinted at in the pthread_setname_np
, the new name is accessible as ps
format specifier comm
, but not args
or command
(which is what is usually printed):
ps H -C <cmd name> -o 'pid tid args comm'
illustrates the difference (adapted from the man
page). I haven't been able to find a good piece of documentation that discusses this explicitly, though.
Here, <cmd name>
is the name of your program's binary.
Python thread name doesn't show up on ps or htop
First install the prctl module. (On debian/ubuntu just type sudo apt-get install python-prctl
)
from threading import Thread
import time
import prctl
def sleeper():
prctl.set_name("sleeping tiger")
while True:
time.sleep(10)
print "sleeping"
t = Thread(target=sleeper, name="Sleeper01")
t.start()
t.join()
This prints
$ ps -T
PID SPID TTY TIME CMD
22684 22684 pts/29 00:00:00 bash
23302 23302 pts/29 00:00:00 python
23302 23303 pts/29 00:00:00 sleeping tiger
23304 23304 pts/29 00:00:00 ps
Note: python3 users may wish to use pyprctl.
Can Windbg display thread names?
For .NET threads, the following works for "normal" Thread
s (manually created threads, since I don't know a way to name threadpool threads):
A Thread
is a class and thus can be found in the .NET managed heap:
0:000>.loadby sos clr
0:000> !dumpheap -stat -type Thread
MT Count TotalSize Class Name
...
725e4960 11 572 System.Threading.Thread
Note that there is other output as well, since !dumpheap
looks for parts of class names. The Method Table (MT) however, identifies a class uniquely, so that's what we use from now on:
0:000> !dumpheap -short -mt 725e4960
023123d0
02312464
02313c80
...
These are the addresses of Thread
objects. Since it is clean output, we can use it in a loop:
0:000> .foreach (address {!dumpheap -short -mt 725e4960}) {.echo ${address} }
023123d0
02312464
02313c80
...
Inside the loop, we can use the address to get more information about the thread. First, let's find out how a Thread looks like internally:
0:000> !do 023123d0
Name: System.Threading.Thread
...
Fields:
MT Field Offset Type VT Attr Value Name
...
725e3e18 400076e c System.String 0 instance 02313c0c m_Name
...
At offset +0xC
(depending on the bitness!), there's the m_Name
member. That's a string. Let's find out how a string looks like:
0:000> !do poi(023123d0+c)
Name: System.String
...
Fields:
MT Field Offset Type VT Attr Value Name
...
725e4810 40000ac 8 System.Char 1 instance 4d m_firstChar
So, the first character of the string is at offset +0x08
. Strings in .NET are Unicode, so we can view it with du
:
0:000> du poi(023123d0+c)+8
02313c14 "My named thread 0"
Combine all this knowledge into a single command:
.foreach (address {!dumpheap -short -mt 725e4960})
{
du poi(${address}+c)+8
}
(formatted for readability, put it all in one line)
If you try that, you'll find that it may output something like
00000008 "????????????????????????????????"
This happens when m_Name
is null
. If you care about that, you can add a check for null:
.foreach (address {!dumpheap -short -mt 725e4960})
{
.if (poi(${address}+c) != 0) {
du poi(${address}+c)+8
}
}
(formatted for readability, put it all in one line)
Other improvements:
- do the same for the thread ID
- prettify output (use
.printf
instead ofdd
anddu
)
Final result:
.foreach (address {!dumpheap -short -mt 725e4960})
{
.if (poi(${address}+c) != 0)
{
.printf "%d ",poi(${address}+28);
.printf "%mu\r\n", poi(${address}+c)+8
}
}
How to set the name of a thread in Linux pthreads?
Use the prctl(2)
function with the option PR_SET_NAME
(see the docs).
Note that old versions of the docs are a bit confusing. They say
Set the process name for the calling process
but since threads are light weight processes (LWP) on Linux, one thread is one process in this case.
You can see the thread name with ps -o cmd
or with:
cat /proc/$PID/task/$TID/comm
or in between the ()
of cat /proc/$PID/task/$TID/stat
:
4223 (kjournald) S 1 1 1 0...
or from GDB info threads
between double quotes:
* 1 Thread 0x7ffff7fc7700 (LWP 6575) "kjournald" 0x00007ffff78bc30d in nanosleep () at ../sysdeps/unix/syscall-template.S:84
p_thread set thread name not showing up in htop
I figured it out. I had a filter in htop, and that was hiding my named threads. Once I removed that filter, it showed.
Perl threads- can they be named uniquely? (Linux)
Update 2020-10-21:
I just discovered an even better way to achieve this - the actual linux syscall. https://man7.org/linux/man-pages/man2/prctl.2.html
Troels Liebe Bentsen has kindly contributed a module that handles this neatly.
https://metacpan.org/pod/Sys::Prctl
Far more seamless than fiddling with $0 !!!
Original Post content continues below....
ps -T -p 126193
PID SPID TTY TIME CMD
126193 126193 pts/11 00:00:00 test2.pl
126193 126194 pts/11 00:00:00 __thr1 #<--- now unique
126193 126195 pts/11 00:00:00 __thr2 #<--- now unique
top -H -p 126193
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
126193 xxxxxxx+ 20 0 305948 7972 2244 S 0.0 0.0 0:00.01 test2.pl
126194 xxxxxxx+ 20 0 305948 7972 2244 S 0.0 0.0 0:00.00 __thr1
126195 xxxxxxx+ 20 0 305948 7972 2244 S 0.0 0.0 0:00.00 __thr2
##################
Thanks to @ikegami , I found a solution that will work.
Couple of small changes were needed in order to get keep the child threads alive, and also needed to stop the main thread from joining them back in. (Based on how it behaves, I assume that if the child threads reach the end of the sub they are spawned with, they are completely terminated and Linux cleans them up - even though the main thread hasn't called join
on them yet.
To anyone else reading this page in future, I would love to know why each of pstree, ps, and top, all show a different result.
Any how, leaving this info and comparisons here in case its helpful to others.
End result:
- Using
ps
command , it does NOT appear to be possible to get the modified name of the threads. It only shows the string of what the last thread that touched $0 set it to - Similarly, using pstree
pstree -p -a -l 144741
also only shows the main thread as the name for each child, and does not show anything about the changes made by the threads - But, very fortunately, using top works!!!!
top -H -b -p 180547
, which clearly shows the main thread, and all child threads by the name they set using $0
Example from ps:
app_sy+ 180547 131203 180547 0 3 18:08 pts/1 00:00:00 thr2
app_sy+ 180547 131203 180548 0 3 18:08 pts/1 00:00:00 thr2
app_sy+ 180547 131203 180549 0 3 18:08 pts/1 00:00:00 thr2
Example using pstree:
test.pl,180547
|-{test.pl},180548
`-{test.pl},180549
And the winner, using top -n 1 -H -b -p 180547
, which shows the distinct names applied to $0 by each thread successfully!!!!!!
top - 18:00:08 up 69 days, 8:53, 3 users, load average: 4.10, 3.95, 4.05
Threads: 3 total, 0 running, 3 sleeping, 0 stopped, 0 zombie
%Cpu(s): 7.7 us, 33.5 sy, 0.0 ni, 58.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 13144056+total, 1351640 free, 45880316 used, 84208608 buff/cache
KiB Swap: 16777212 total, 16777212 free, 0 used. 78196224 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
180547 app_+ 20 0 299572 7152 2144 S 0.0 0.0 0:00.00 test.pl
180548 app_+ 20 0 299572 7152 2144 S 0.0 0.0 0:00.02 thr1
180549 app_+ 20 0 299572 7152 2144 S 0.0 0.0 0:00.01 thr2
Adding Modified version of Ikegami's code here for future reference for others looking at this page, saved as test.pl :
#!/usr/bin/perl
use strict;
use warnings;
use feature qw( say );
use threads;
use threads::shared;
my $phase :shared = 0;
my $main_pid = $$;
sub advance {
lock $phase;
++$phase;
cond_signal($phase);
}
sub wait_for {
lock $phase;
cond_wait($phase) while $phase != $_[0];
}
sub advance_and_wait_for {
lock $phase;
++$phase;
cond_signal($phase);
cond_wait($phase) while $phase != $_[0];
}
my $thr1 = async {
my $id = 'thr1';
wait_for(0);
advance_and_wait_for(2);
say "[$id] Setting \$0 to $id.";
$0 = $id;
say "[$id] \$0 = $0";
print `ps -eLf|grep $main_pid` =~ s/^/[$id] /mrg;
advance_and_wait_for(4);
say "[$id] \$0 = $0";
advance();
while(1){
sleep 1;
}
};
my $thr2 = async {
my $id = 'thr2';
wait_for(1);
advance_and_wait_for(3);
say "[$id] \$0 = $0";
say "[$id] Setting \$0 to $id.";
$0 = $id;
say "[$id] \$0 = $0";
print `ps -eLf| grep $main_pid` =~ s/^/[$id] /mrg;
advance();
while(1){
sleep 1;
}
};
sleep 5;
print "Main thread pid is $main_pid - and \$0 is ($0)\n";
my $waitfor = <STDIN>;
$_->join for $thr1, $thr2;
Related Topics
Linux Execute Command Remotely
How to Terminate a Sleeping Thread in Pthread
Vagrant Synced Folders Not Working Real-Time on Virtualbox
Warning Building a Kernel Module That Uses Exported Symbols
How to Access an Environment Variable in a .Desktop File's Exec Line
Why Disabling Interrupts Disables Kernel Preemption and How Spin Lock Disables Preemption
Rm: Cannot Remove: Permission Denied
Socat Terminates After Connection Close
What Do the .Eh_Frame and .Eh_Frame_Hdr Sections Store, Exactly
What Is the Use of _Iomem in Linux While Writing Device Drivers
Can Not Connect to Linux "Abstract" Unix Socket
X Keypress/Release Events Capturing Irrespective of Window in Focus
What Does a Hexadecimal Number, with a Register in Parenthesis Mean in Assembly