Change process name in Linux

One of the comments mentions prctl, but this really deserves its own answer, because setting argv[0] will not work in all cases (it does nothing on my system).

There are at least two library calls to set the name of a thread in Linux, both limited to 15 characters plus the terminating NUL byte:

  1. glibc-specific: pthread_setname_np(...) where the np stands for "non-portable", but this might be present on some other OSes: https://linux.die.net/man/3/pthread_setname_np
  2. Linux-specific: prctl(PR_SET_NAME...) which is also non-portable: https://linux.die.net/man/2/prctl

Example

Here's a test of the different methods (with no error handling):

// gcc pstest.c -o pstest -O2 -Wall -Wextra -Werror -Wno-unused -Wno-unused-result -std=gnu99 -pthread -D_GNU_SOURCE 
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/prctl.h>

int main(int argc, char *argv[])
{
    puts("Initial ps output:");
    system("ps | grep pstest");

    puts("\npthread_setname_np");
    pthread_setname_np(pthread_self(), "setname");
    system("ps | grep setname");

    puts("\nprctl");
    prctl(PR_SET_NAME, (unsigned long)"prctl", 0, 0, 0);
    system("ps | grep prctl");

    puts("\nargv[0]");
    argv[0] = "argv0";
    system("ps | grep argv0");

    return 0;
}

Notice the lack of output after argv[0]:

./pstest
Initial ps output:
17169 pts/0    00:00:00 pstest

pthread_setname_np
17169 pts/0    00:00:00 setname

prctl
17169 pts/0    00:00:00 prctl

argv[0]

In the wild

Here's an example in production code (as always, be sure to take note of the license when looking at code on GitHub)

See also

See also these questions and answers:

  • https://unix.stackexchange.com/questions/167490/how-can-a-process-appear-to-have-different-name-in-ps-output
  • Using prctl PR_SET_NAME to set name for process or thread?

I think this should work, to illustrate the principle...

#include <stdio.h>

int main(int argc, char *argv[]) {
  argv[0][0] = 65;
  sleep(10);
}

will change the name, and put an "A" instead of the first letter. CtrlZ to pause, then run ps to see the name changed. I have no clue, but it seems somewhat dangerous, since some things might depend on argv[0].

Also, I tried replacing the pointer itself to another string; no cigar. So this would only work with strcpy and strings shorter or equal than the original name.

There might or might not be a better way for this. I don't know.

EDIT: nonliteral solution: If you're forking, you know the child's PID (getpid() in the child, result of fork() in the parent). Just output it somewhere where you can read it, and kill the child by PID.

another nonliteral solution: make softlinks to the executable with another name (ln -s a.out kill_this_a.out), then when you exec, exec the link. The name will be the link's name.


This is a non-portable hack:

/*
 * Sets process title, truncating if there is not enough space, 
 * rather than causing memory corruption.
 */
void set_title_np(int argc, char **argv, const char *title) {
    // calculate available size
    size_t space = 0;
    for (int i = 0; i < argc; i++) {
        size_t length = strlen(argv[i]);
        space += length + 1; // because of terminating zero 
    }
    memset(argv[0], '\0', space); // wipe existing args
    strncpy(argv[0], title, space - 1); // -1: leave null termination, if title bigger than space
} 

According to this comment, prctl(PR_SET_NAME) only affects the "short name" of a thread. It has the same effect as writing into /proc/self/comm.

To change the "long name" (/proc/self/cmdline which is actually used by htop and ps u) you need some ugly hack (which is mentioned in that comment but the link is dead). An example of this kind of hack can be found in Chromium source code: https://source.chromium.org/chromium/chromium/src/+/master:content/common/set_process_title_linux.cc

Tags:

Linux

C

Process