Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to start a process in its own process group?

I would like to start a process in its own process group (or, alternatively, change its group once started) and:

  • have the processes in the group respond to Ctrl + C from the terminal
  • get the id of the process group so that I can terminate all the processes in the group via the kill command.

Note: I tried setsid prog [args] but the processes do not respond to Ctrl+C from the terminal nor I could get the new process group id.

I also tried to change the process group via Perl's setpgrp($pid, $pid) and POSIX::setpgid($pid, $pid), to no avail.

Edit: The larger problem:

I have a process (single-threaded; let's call it the "prolific" process P) that starts many child processes synchronously (one after another; it starts a new one when the previous child process terminates). From the terminal, I want to be able to kill P and the tree of processes below it. To do that, I could simply arrange to kill the processes in P's group. However, the default behavior is that P is in the group of its parent process. That means that P's parent will be killed if I kill all the processes in P's group, unless I have P and its tree be in their own group.

My intention is to kill P and the tree below it, but not P's parent. Also, I cannot modify P's code itself.

like image 883
beluchin Avatar asked Apr 27 '11 18:04

beluchin


People also ask

What is a group of processes called?

The group of processes in a process group is sometimes referred to as a job and is manipulated as a single entity by processes such as the shell. Some signals (e.g., SIGINT) are delivered to all members of a process group, causing the group as a whole to suspend or resume execution, or to be interrupted or terminated.

What is group PID?

Sets the process group ID (PGID) of a process within the session of the calling process, so you can reassign a process to a different process group, or start a new process group with the specified process as its group leader. pid_t pid is the process ID (PID) of the process whose PGID you want to change.

What is process group mechanism?

In a POSIX-conformant operating system, a process group denotes a collection of one or more processes. Among other things, a process group is used to control the distribution of a signal; when a signal is directed to a process group, the signal is delivered to each process that is a member of the group.

What is process group in Linux?

A process group in Linux, as the name suggests, is a way that Linux groups process together. They are a collection of related processes sharing the same PGID's (Process Group ID). A common misconception is that killing the parent process will kill the children's processes too.


3 Answers

What do you mean "start a process in its own process group"? The shell launches processes in their own process groups, that's how it does job control (by having a process group for processes in the foreground, and several process groups for every pipeline launched on the background).

To see that the shell launches a new process group for every pipeline, you can do this:

ps fax -o pid,pgid,cmd | less

which will show something like:

11816 11816  |   \_ /bin/bash
4759   4759  |       \_ ps fax -o pid,pgid,cmd
4760   4759  |       \_ less

Note that the shell has created a new process group for the pipeline, and every process in the pipeline shares the process group.

Edit:

I think I know what you are getting at. You are calling system from Perl. Apparently, sh -c doesn't create new process groups, since it's a shell without job control.

What I would do would be to fork, then on the child:

setpgrp;
system("ps fax -o pid,pgid,cmd");

and wait on the parent.

like image 53
ninjalj Avatar answered Nov 09 '22 20:11

ninjalj


EDIT: If what you wanted to do was use setsid but find the session id and/or pid of the resulting process:

If you launch a process through the setsid command it won't be attached to your terminal, so of course it won't respond to ctrl-c.

You could find it by grepping through the output of

ps x -O sid 

or something more limited like

ps x -o %c,%p,sid

Or simple trolling through proc/[pid]/stat for all entries and looking at the session id and whatever else is of interest (see man proc for details)

The man page for setsid is not giving any flags to directly generate output, but you could trivially make your own version that prints out the desired information, by modifying the standard.

For example, grab a copy of setsid.c from one of the results for

http://www.google.com/codesearch?as_q=setsid&as_package=util-linux

Comment out the nls include, the locale stuff and the _("") error macro which will cause problems and then add this right before the execvp line:

    printf("process will be pid %d sid %d\n", getpid(), getsid(0));
like image 45
Chris Stratton Avatar answered Nov 09 '22 18:11

Chris Stratton


Here is the answer in Perl code following ninjalj's suggestions above:

prolific_wrapper.pl

my $pid = fork();
if (not defined $pid) {

    die 'resources not available';

} elsif ($pid == 0) {

    # CHILD
    setpgrp;
    exit system(prolific => @ARGV);

} else {

    # PARENT
    my $was_killed = 0;
    local $SIG{INT} = sub {
        say 'kill prolific and its tree ...';
        kill KILL => -$pid;
        $was_killed = 1;
    };
    wait;
    my $child_status = $?;
    $SIG{INT} = 'DEFAULT';
    if ($was_killed) {kill INT => $$}
    else {exit $child_status}

}

Many thanks again!

like image 1
beluchin Avatar answered Nov 09 '22 19:11

beluchin