Specifying the name of the successor

No, we are not debating how to hack who will succeed Queen Elizabeth II to the throne here, sorry. What we are referring to is this: How can you correctly specify the name of the successor process; that is, can we programmatically change it to whatever we like?

At first glance, it looks trivial indeed: The second parameter to the execl is the argv[0] argument to pass to the successor; in effect, it appears, its name! So, let's try it out: We write a couple of C programs; the first one, the predecessor (ch9/predcs_name.c) is passed a name parameter from the user. It then execs another program of ours, successor_setnm  via the execl passing along the user-supplied name as the first parameter (within the API, it sets the successor argv[0] parameter to the predecessor's argv[1]), like so: execl("./successor_setnm", argv[1], argv[1], (char *)0);

Recall the execl syntax: execl(pathname_to_successor_program, argv0, argv1, ..., argvn, 0);

So, the thinking here is: The predecessor has set the successor's argv[0] value to argv[1], and thus the successor's name should be the predecessor's argv[1]. However, it does not work out; see the output from a sample run:

$ ./predcs_name 
Usage: ./predcs_name {successor_name} [do-it-right]
$ ./predcs_name UseThisAsName &
[1] 12571
UseThisAsName:parameters received:
argv[0]=UseThisAsName
argv[1]=UseThisAsName
UseThisAsName: attempt to set name to 1st param "UseThisAsName" [Wrong]
UseThisAsName: pausing now...
$
$ ps
PID TTY TIME CMD
1392 pts/0 00:00:01 Bash
12571 pts/0 00:00:00 successor_setnm
12576 pts/0 00:00:00 ps
$

We deliberately have the successor process invoke the pause(2) system call (it simply causes it to sleep until it receives a signal). This way, we can run it in the background, and then run ps to lookup the successor PID and name!

Interesting: We find that, though the name is not what we want in ps output (above), it is correct in the printf; implying that argv[0] has been correctly received and set to the successor.

OK, we must clean up; lets kill off the background process now:

$ jobs
[1]+ Running ./predcs_name UseThisAsName &
$ kill %1
[1]+ Terminated ./predcs_name UseThisAsName
$

So, as is now apparent, what we've done preceding is not enough: To reflect the name we want at the level of the OS, we need an alternate API; one such API is the prctl(2) system call (or even the pthread_setname_np(3) pthreads API). Without getting into too much detail here, we use it with the PR_SET_NAME parameter (as usual, please see the man page on prctl(2) for full details). Hence, the correct code using the prctl(2) system call (only the relevant code snippet from successor_setnm.c is displayed here):

[...]
if (argc == 3) { /* the "do-it-right" case! */
printf("%s: setting name to "%s" via prctl(2)"
" [Right] ", argv[0], argv[2]);
if (prctl(PR_SET_NAME, argv[2], 0, 0, 0) < 0)
FATAL("prctl failed ");
} else { /* wrong way... */
printf("%s: attempt to implicitly set name to "%s""
" via the argv[0] passed to execl [Wrong] ",
argv[0], argv[1]);
}
[...]
$ ./predcs_name 
Usage: ./predcs_name {successor_name} [do-it-right]
$

So, we  now run it the right way (the logic involves passing along an optional second parameter which will be used to _correctly_ set the successor process name):

$ ./predcs_name NotThis ThisNameIsRight &
[1] 12621
ThisNameIsRight:parameters received:
argv[0]=ThisNameIsRight
argv[1]=NotThis
argv[2]=ThisNameIsRight
ThisNameIsRight: setting name to "ThisNameIsRight" via prctl(2) [Right]
ThisNameIsRight: pausing now...
$ ps
PID TTY TIME CMD
1392 pts/0 00:00:01 Bash
12621 pts/0 00:00:00 ThisNameIsRight
12626 pts/0 00:00:00 ps
$ kill %1
[1]+ Terminated ./predcs_name NotThis ThisNameIsRight
$

This time it works exactly as expected.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset