2

I have a program(A) that starts another program(B).

What I want is when every time B receives signal A sends this signal to B and all child processes of B. I don't really know how to implement a few things here:

1). How do I determine that signal was sent to B?

2). How do I save this signal in variable?

3). How do I loop until B is alive?

int main() {
   pid_t pid = fork();
   int32_t num = 0;
   if (pid == 0) {
      static char *argv[] = {"main", NULL};
      execv(argv[0], argv); //start program B
   }
   else{
      while(/*B is alive*/){
          //if program B receives signal
          //I want to send this signal to B and all child processes, 
          //cause B doesn't handle any signals
          if (/*B receives signal*/){
              //save this signal to num.
              kill(pid, num); //???
                              //send signal to parent
                              //useless cause it was already send to B?
              fp = popen((("pgrep -P ") + string(num)).c_str(), "r");
              //pgrep all child processes
              std::vector<int> children;
              while (fgets(buf, 128, fp) != NULL) //getting child pid
                  children.push_back(stoi(string(buf)));
              for(auto a : children)              
                  kill(a, num); //send signal to child
         }
      }
   } 
   return 0;
}
user23316192
  • 69
  • 1
  • 7

1 Answers1

3

I am afraid your question is really too broad and it involves too many topics. I will try anyway to help if possible.

About Signal handling. I usually spwan a separate thread in my program that is just dedicated to signal handling. In this way, I won't "disturb" the main execution.

About how to handle signals, please have a look to this code snippet:

void    *   threadSignalHandler (){
int err, signo;

for (;;) {
    err = sigwait(&mask, &signo);
    if (err != 0) {
        syslog(LOG_ERR, "sigwait failed");
        exit(1);
    }

    switch (signo) {
    case SIGHUP:
        //Do your stuff here

        break;

    case SIGTERM:
        //Do your stuff here 
        break;
    default:
        syslog(LOG_INFO, "unexpected signal %d\n", signo);
        break;
    }
}
return(0);

}

Again, as exaplined, I usually spawn a new basic thread and I do it with in this way:

    int                 err;
    pthread_t           tid;

 /*
    * Restore SIGHUP default and block all signals.
    */
   sa.sa_handler = SIG_DFL;
   sigemptyset(&sa.sa_mask);
   sa.sa_flags = 0;
   if (sigaction(SIGHUP, &sa, NULL) < 0)
       err_quit("%s: can′t restore SIGHUP default");
   sigfillset(&mask);
   if ((err = pthread_sigmask(SIG_BLOCK, &mask, NULL)) != 0)
       err_exit(err, "SIG_BLOCK error");



    /*
    * Create a thread to handle SIGHUP and SIGTERM.
    */
   err = pthread_create(&tid, NULL, threadSignalHandler, 0);
   if (err != 0)
       err_exit(err, "can′t create thread");

So, to answer your 3 questions:

A) Use the code I provided, it is tested and I know it works.

B) Just modify the thread handler to store the signal received (variable signo)

C) Please have a look here, there are consolidated ways to do it, according to posix standards (Check if process exists given its pid)

Community
  • 1
  • 1
Maurizio Benedetti
  • 3,557
  • 19
  • 26