Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

notify parent process when child process dies

Say i have a parent process that spawns few workers (child processes). I would like to get notified when one of the child processes crashes (gets killed).

What is the best way to get this notification. I am programming in c or c++. I am on unix. And have spawned hte child processes using fork_and_exec

like image 372
AMM Avatar asked Nov 29 '25 21:11

AMM


1 Answers

In case you only want to get notification when child process exits (normally or abnormally), you can write a handler to SIGCHLD signal in parent process. This handler will be executed whenever a process that was spawned by this process dies.

However, there are serious limitations on what you can do inside of this handler. In case other signal is received, this handler will be immediately interrupted. Even variable assignment is not a safe operation inside of the signal handler - assignment can take two or more machine instructions, and it can be interrupted by a new signal leaving the value undefined. The only variables that can safely be assigned inside of the signal handler are those of type sig_atomic_t (assignment to variable of this type is guaranteed to be completed in one instruction).

Parent also has to "wait" (using wait function) for child process - otherwise, child process will become zombie after termination.

This solution was sufficient in my case as I only had to decrement the counter variable of type sig_atomic_t. If you need to do some "serious" processing when child dies, other solution is needed. The idea might be as follows:

  • Inside the main process, have a dedicated thread that will wait for children's death (this includes successfully returning from main, killed by SIGTERM and SIGKILL signals and any other abnormal termination).
  • For this purpose we can use UNIX waitid() method which lets us specify the children we are waiting for, type of event we are waiting for (EXITED, STOPPED or CONTINUED) and on success gives us useful info about the terminated process (such as child's PID).
  • So, inside of this thread we use waitid() to wait for children and each time a child dies this function terminates giving us useful info.
  • After waitid() returns we should check its return value and errno to see if everything went ok. If yes, we can perform our cleanup procedure (the block of code that we want to execute when child dies) and then we continue listening for more deaths (as awful as it sounds).

C++ sample can be found below - please note I'm not using a thread to wait for children, but it shouldn't be hard to modify the example to use a thread.

#include <iostream>
#include <sys/types.h>
#include <unistd.h>

int spawn(char* process_name, char** arguments){
    pid_t child_id = fork();

    if (child_id != 0)
        return child_id;
    else{
        execvp(process_name, arguments);
        fprintf(stderr, "An error occured while executing new process.\n");
        abort();
    }
}


int main(int argc, const char * argv[])
{
    char* arguments[] = {
        "/Path_to_Child_Exe/Child_Process",
        nullptr
    };

    int i=0;
    while (i++ < 10)
        spawn((char*) "/Path_to_Child_Exe/Child_Process", arguments);


    while (true){
        siginfo_t exit_info;
        int retVal = waitid(P_ALL, -1, &exit_info, WEXITED);

        if (retVal == -1 && errno == ECHILD){
            std::cout << "No more children.\n";
            break;
        }

        std::cout << "Child with PID " << exit_info.si_pid << " terminated.\n";

        sleep(1);
    }

    return 0;
}

It is also important to notice that we call sleep at the end of each iteration of while loop. The same should be done within the thread waiting for children. Otherwise, if we would call the waitid() function without pause when there are no child processes, CPU usage would be very high (a form of busy waiting I guess). Because of this we must call sleep every now and then to give CPU a chance to rest.

like image 175
dbajgoric Avatar answered Dec 04 '25 22:12

dbajgoric



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!