I've found this post about changing the name of a thread.
I tried the prctl()
and pthread_setname_np()
functions. Both change the name of ALL my threads. In other words, it doesn't seem to work as expected.
I used:
pthread_setname_np(pthread_self(), "thread ONE");
and
pthread_setname_np(pthread_self(), "thread TWO");
Depending on which runs first, both threads say "thread ONE" or "thread TWO". I was expecting one of them to be "thread ONE" and the other to be "thread TWO".
Am I doing something wrong?
As proposed by Tzig in a comment, I tested the example as shown in the pthread_setname_np() documentation. However, I needed to test with at least two threads so I changed the code as follow to have a thread1 and thread2.
By default, I can start htop
and use F4 to only show threads/processes with names including THREAD
(I can also use the command line to use a different name: ./a.out MULTIFOO MULTIBAR
and then use the word MULTI
as the filter).
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#define NAMELEN 16
#define errExitEN(en, msg) \
do { errno = en; perror(msg); \
exit(EXIT_FAILURE); } while (0)
static void *
threadfunc(void *parm)
{
sleep(15); // allow main program to set the thread name
return NULL;
}
int
main(int argc, char **argv)
{
pthread_t thread1, thread2;
int rc;
char thread_name[NAMELEN];
rc = pthread_create(&thread1, NULL, threadfunc, NULL);
if (rc != 0)
errExitEN(rc, "pthread_create");
rc = pthread_create(&thread2, NULL, threadfunc, NULL);
if (rc != 0)
errExitEN(rc, "pthread_create");
// test name of thread1
//
rc = pthread_getname_np(thread1, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("Created thread1. Default name is: %s\n", thread_name);
rc = pthread_setname_np(thread1, (argc > 1) ? argv[1] : "THREADFOO");
if (rc != 0)
errExitEN(rc, "pthread_setname_np");
sleep(2);
rc = pthread_getname_np(thread1, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("The thread1 name after setting it is %s.\n", thread_name);
// test name of thread2
//
rc = pthread_getname_np(thread2, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("Created thread2. Default name is: %s\n", thread_name);
rc = pthread_setname_np(thread2, (argc > 2) ? argv[2] : "THREADBAR");
if (rc != 0)
errExitEN(rc, "pthread_setname_np");
sleep(2);
rc = pthread_getname_np(thread2, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("The thread2 name after setting it is %s.\n", thread_name);
// thread1 name changed too?
//
rc = pthread_getname_np(thread1, thread_name, NAMELEN);
if (rc != 0)
errExitEN(rc, "pthread_getname_np");
printf("The thread1 name after setting thread2 name is %s.\n", thread_name);
rc = pthread_join(thread1, NULL);
if (rc != 0)
errExitEN(rc, "pthread_join");
rc = pthread_join(thread2, NULL);
if (rc != 0)
errExitEN(rc, "pthread_join");
printf("Done\n");
exit(EXIT_SUCCESS);
}
P.S. There is a bug in the original:rc = pthread_getname_np(thread, thread_name, (argc > 2) ? atoi(argv[1]) : NAMELEN);
Notice that the
atoi()
usesargv[1]
instead ofargv[2]
. (I have reported the bug to the man-pages maintainers.)
In my example, I use the second argument as the name of the second thread and always use NAMELEN
as the length of my buffer. I have no reason for reducing that amount.
RESULTS:
As expected, the pthread_getname_np()
works. Great!
However, the htop
or cat /proc/self/task/<tid>/comm
all return the last name that was set. I guess that's a bug in the Linux kernel... Yet, my process has other threads created by the NVidia driver and those have different names.
Just in case, I tried the functions found in Linux - how to change info of forked processes in C which did seem wrong since it says "fork()'ed". But since each task has its own entry under /proc
... but the issue, I suppose, is that the threads share the same memory as their main process and there is only one location for the argv[0]
data. In other words, they implemented a pthread_setname_np()
which works internally, but does not reflect that name in tools such as ps
and htop
.