Reuben Tanner
Reuben Tanner

Reputation: 5565

Kill all child processes of a parent but leave the parent alive

What would be the best way to kill all the processes of a parent but not the parent? Let's say I have an undetermined number of child processes that I've forked and on a given alarm, in my signal handler, I'd like to kill all my child processes but keep myself running for various reasons.

As of now, I am using kill(-1*parentPid, SIGKILL) but this kills my parent along with its children.

Upvotes: 7

Views: 39469

Answers (4)

I have an idea by using sigaction.

void my_function(int signum)
{
    // Revert to the default signal handler
    signal(signum, SIG_DFL);
}

void create_n_child_process(unsigned int n)
{
    pid_t child_pid;

    for(unsigned int i=0 ; i < n ; i++) // loop will run n times (n=5)
    {
        child_pid = fork();
        if(child_pid == 0)
        {
            printf("[son] pid %d from [parent] pid %d\n",getpid(),getppid());
            exit(0);
        }
    }
    // the parent
    // Here the children processes do not run

    struct sigaction sa;
    sa.sa_handler = my_function;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;

    sigaction(SIGTERM, &sa, NULL); // Install the signal handler for SIGTERM

    if (killpg(getpid(), SIGTERM) == -1) {
        perror("killpg");
        exit(EXIT_FAILURE);
    }

    std::cout << "I continue to run" << std::endl;

}

int main(int argc, char** argv)
{
    unsigned int number_of_child_processes = 5;
    create_n_child_process(number_of_child_processes);
    return 0;
}

In my program, you try to launch 5 processes. However, you execute some of them and then you kill the children processes.

You can use this program as a skeleton and return a value from the children processes using wait(&status) where the status variable contains the value returned by the children processes.

Upvotes: 0

jxh
jxh

Reputation: 70502

One way to accomplish this is to deliver some signal that can be caught (not SIGKILL). Then, install a signal handler that detects if the current process is the parent process or not, and calls _exit() if it is not the parent process.

You could use SIGUSR1 or SIGUSR2, or perhaps SIGQUIT.

I've illustrated this technique here.

Optionally (as suggested by Lidong), the parent process can use SIG_IGN on the signal before issuing the kill() command.

signal(SIGQUIT, SIG_IGN);
kill(0, SIGQUIT);

Upvotes: 6

f_x_p
f_x_p

Reputation: 58

you can set the child process a new process group at the fork time, and while you want to kill the child process and its descendants, you can use killpg, example code as:

#include <unistd.h>
#include <signal.h>
#include <stdio.h>

void parent(pid_t pid) {
    killpg(pid, SIGKILL);
}

void child(void) {
    if (-1 == setsid())
        return;

    while(1) {
        sleep(1);
        printf("child\n");
    } 
}


int main() {
    pid_t pid;
    switch ((pid=fork())) {
    case 0: // child
        child();
        break;

    default: // parent
        getchar();
        getchar();
        parent(pid);
    }

    return 0;
}

Upvotes: 4

Lidong Guo
Lidong Guo

Reputation: 2857

Jxh 's answer is nice. Howevr , maybe you can just give a signal hander for every children process after fork and let it call exit function . and you give a signal hander for parent and let it ignore the signal (like SIGUSR1). this may add the code lines but you don't need detect the process is parent or child in signal hander function.

Upvotes: 2

Related Questions