Tirtsah Dreyfus
Tirtsah Dreyfus

Reputation: 53

What is the best way to detect when a child process has terminated using signals

I have a process child (created with fork), I want to know in the parent where it dies, and do there something. In the handle function I want to use member-class function, so I have to pass pointer to "this".

I have thought on two way:

Option 1:

use sigaction;

static RpcCmd* rpcCmdPtr = nullptr;// global pointer to save class  

in the main:

  rpcCmdPtr  = this;  
  struct sigaction act;  
  memset(&act, 0, sizeof(act));  
  act.sa_handler = **sigchldHdl**;  
  sigaction(SIGCHLD, &act, 0)  

/* SIGCHLD handler. */  
void **sigchldHdl**(int sig)  
{  
  if(rpcCmdPtr != nullptr)  
  {  
    rpcCmdPtr->sigHandler(sig);  
  }  
}

void RpcCmd::sigHandler(int sig)  
{ // here are some code...}

Option 2:

use another thread, pass pointer to "this" as argument, and use there signalfd;

    static void * sigThread(void * arg)  
    {  
    rpcCmd* rpcCmdPtr = static_cast<rpcCmd*>(arg)  
    sigprocmask(SIG_BLOCK, &mask, NULL)  

    /* Create a file descriptor from which we will read the signals. */  
    sfd = signalfd (-1, &mask, 0);  

    while (1) {  
        struct signalfd_siginfo si;  
        res = read (sfd, &si, sizeof(si));  
        if (si.ssi_signo == SIGCHLD)  
            // more code ...  
    } 

I want to know WHAT is the best way, and WHY?

Thanks in advance.

Upvotes: 0

Views: 554

Answers (2)

Read carefully signal(7) and signal-safety(7) (and remember that most of C++ standard library -including new, containers, etc...- is based upon non async-signal-safe functions like malloc, so you usually cannot call these C++ functions from a signal handler)

You forgot the more portable option 3:

  • at process initialization, create a pipe(7) (to "self" process)

  • before entering your event loop install a read handler for that pipe (it would read(2) bytes from it)

  • install (using sigaction(2)) a signal handler for your signal that simply write(2) one or a few bytes into the pipe. Notice that write is async-signal-safe.

This approach is proposed by Qt, see its Calling Qt Functions From Unix Signal Handlers page.

BTW, many event loop libraries (often above poll(2)...) do handle already SIGCHLD

Upvotes: 3

Zang MingJie
Zang MingJie

Reputation: 5275

option 1 is evil.

  1. only async-signal-safe function can be called inside a signal handler. And lots of function can't be called inside a signal handler, eg malloc free and printf

  2. signal handler must be reentrant, your RpcCmd::sigHandler probably is not reentrant

Upvotes: 1

Related Questions