_GNU_SOURCE


C/C++: Set and Get the name of a pthread

Naming a pthread using meaningful names, can be a very useful feature for debugging multi-threaded applications as it can make your logs very informative.
For this reason, we are presenting two examples demonstrating the use of names in pthreads.

  • [download id=”3786″]
  • [download id=”3788″]

Example 1: The pthread decides for its name

The following code, creates a pthread which later, it will give itself a meaningful name.

[download id=”3786″]


// #define _GNU_SOURCE is needed for the resolution of the following warnings
//warning: implicit declaration of function ‘pthread_setname_np’ [-Wimplicit-function-declaration]
//warning: implicit declaration of function ‘pthread_getname_np’ [-Wimplicit-function-declaration]
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <asm/errno.h>
#include <errno.h>
// #include <stdlib.h> is needed for the resolution of EXIT_SUCCESS
#include <stdlib.h>

//The thread name is a meaningful C language string, whose length is restricted to 16 characters, including the terminating null byte.
#define MAX_LENGTH_PTHREAD_NAME (16)

struct thread_info_t
{
    // Used to identify a thread.
    pthread_t thread_id;
};

// This is the thread that will be called by pthread_create() and it will be executed by the new thread.
void *self_named_thread(void *data)
{
    // We know that the input data pointer is pointing to a thread_info_t so we are casting it to the right type.
    struct thread_info_t *thread_info = (struct thread_info_t *) data;

    const int setname_rv = pthread_setname_np(thread_info->thread_id, "Tom Hanks");
    if (setname_rv)
    {
        errno = setname_rv;
        perror("Could not set pthread name");
    }

    char thread_name[MAX_LENGTH_PTHREAD_NAME];
    const int getname_rv = pthread_getname_np(thread_info->thread_id, thread_name, MAX_LENGTH_PTHREAD_NAME);
    if (getname_rv)
    {
        errno = getname_rv;
        perror("Could not get pthread name");
    }
    //This function always succeeds, returning the calling thread's ID.
    const pthread_t tid = pthread_self();
    //Usually pthread_t is defined as follows:
    //typedef unsigned long int pthread_t;
    //so we print pthread_t as an unsigned long int
    fprintf(stdout, "I am thread with ID '%lu', my name is '%s' and I gave me my name by myself\n", tid, thread_name );

    return NULL;
}

int main()
{
    struct thread_info_t thread_info;

    const int create_rv = pthread_create(&(thread_info.thread_id), NULL, &self_named_thread, (void *) &thread_info);
    if (create_rv)
    {
        errno = create_rv;
        perror("Could not create thread");
        return EXIT_FAILURE;
    }
    // The pthread_join() function suspends execution of the calling thread until the target thread terminates, unless the target thread has already terminated.
    const int join_rv = pthread_join(thread_info.thread_id, NULL);
    if (join_rv)
    {
        errno = create_rv;
        perror("Could not join thread");
    }
    return EXIT_SUCCESS;
}

[download id=”3786″]

Example 2: The parent decides for the pthread name

The next code, creates a pthread and the parent gives the thread a meaningful name.

[download id=”3788″]


// #define _GNU_SOURCE is needed for the resolution of the following warnings
//warning: implicit declaration of function ‘pthread_setname_np’ [-Wimplicit-function-declaration]
//warning: implicit declaration of function ‘pthread_getname_np’ [-Wimplicit-function-declaration]
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <pthread.h>
#include <asm/errno.h>
#include <errno.h>
// #include <stdlib.h> is needed for the resolution of EXIT_SUCCESS
#include <stdlib.h>
// #include <unistd.h> is needed for the resolution of unsigned int sleep(unsigned int seconds);
#include <unistd.h>

//The thread name is a meaningful C language string, whose length is restricted to 16 characters, including the terminating null byte.
#define MAX_LENGTH_PTHREAD_NAME (16)

struct thread_info_t
{
    // Used to identify a thread.
    pthread_t thread_id;
};

// This is the thread that will be called by pthread_create() and it will be executed by the new thread.
void *self_named_thread(void *data)
{
    // We know that the input data pointer is pointing to a thread_info_t so we are casting it to the right type.
    struct thread_info_t *thread_info = (struct thread_info_t *) data;

    //Added an artificial delay for the sake of the example.
    //Making sure the parent thread gave the pthread a name.
    sleep(1);

    char thread_name[MAX_LENGTH_PTHREAD_NAME];
    const int getname_rv = pthread_getname_np(thread_info->thread_id, thread_name, MAX_LENGTH_PTHREAD_NAME);
    if (getname_rv)
    {
        errno = getname_rv;
        perror("Could not get pthread name");
    }
    //This function always succeeds, returning the calling thread's ID.
    const pthread_t tid = pthread_self();
    //Usually pthread_t is defined as follows:
    //typedef unsigned long int pthread_t;
    //so we print pthread_t as an unsigned long int
    fprintf(stdout, "I am thread with ID '%lu', my name is '%s' and my parent gave me my name\n", tid, thread_name );

    return NULL;
}

int main()
{
    struct thread_info_t thread_info;

    const int create_rv = pthread_create(&(thread_info.thread_id), NULL, &self_named_thread, (void *) &thread_info);
    if (create_rv)
    {
        errno = create_rv;
        perror("Could not create thread");
        return EXIT_FAILURE;
    }

    const int setname_rv = pthread_setname_np(thread_info.thread_id, "Bob Marley");
    if (setname_rv)
    {
        errno = setname_rv;
        perror("Could not set pthread name");
    }

    // The pthread_join() function suspends execution of the calling thread until the target thread terminates, unless the target thread has already terminated.
    const int join_rv = pthread_join(thread_info.thread_id, NULL);
    if (join_rv)
    {
        errno = create_rv;
        perror("Could not join thread");
    }
    return EXIT_SUCCESS;
}

[download id=”3788″]