Why I can't catch the signal in the child whic

2019-08-03 17:05发布

问题:

I just learning about signals in C, and I want to send a signal from parent to child, but I can't understand why the handler isn't working here...

My code:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>

void handler(int signumber){
  printf("Signal with number %i has arrived\n",signumber);
}

int main(){

  sigset_t sigset;
  sigemptyset(&sigset); //empty signal set
  sigaddset(&sigset,SIGTERM); //SIGTERM is in set
  //sigfillset(&sigset); //each signal is in the set
  sigprocmask(SIG_BLOCK,&sigset,NULL); //signals in sigset will be blockedhere

  signal(SIGTERM,handler); //signal and handler is connetcted

  pid_t child=fork();
  if (child>0)
  {
    printf("I'm parrent\n");
    printf("Waits 2 seconds, then send a SIGTERM %i signal (it is blocked)\n",SIGTERM);
    sleep(2);
    kill(getppid(),SIGTERM); 
    printf("I sent it.\n");   
  }
  else
  {
    wait(NULL);
    sleep(2);
    printf("I'm the child wainting for signal.\n");

    sigprocmask(SIG_UNBLOCK,&sigset,NULL); 


    int status;
    wait(&status);
    printf("Child process ended\n");
  }
  return 0;
}

And this is the result:

I'm parrent
Waits 2 seconds, then send a SIGTERM 15 signal (it is blocked)
I'm the child wainting for signal.
Child process ended
I sent it.

And one more thing, I know, I have to use sigsuspend(sigset); instead of handler, because the printf isn't safe in handler, but How can I use it in this case?

回答1:

Wait is mainly for reaping child statuses (generally for observing child status changes). Using it in the child doesn't make much sense. Yes, you can use sigsuspend to wait for the signal. It could look like this:

#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>


#define WRITE(Str) (void)write(1,Str,strlen(Str))
void handler(int signumber)
{
    WRITE("Signal arrived\n");
}

int main(){

  sigset_t sigset;
  sigemptyset(&sigset); //empty signal set
  sigaddset(&sigset,SIGTERM); //SIGTERM is in set
  sigprocmask(SIG_BLOCK,&sigset,NULL); //signals in sigset will be blockedhere

  signal(SIGTERM,handler); //signal and handler is connetcted

  pid_t child=fork();
  if(0>child) return EXIT_FAILURE;
  if (child>0) {
    int status;
    printf("I'm the parent\n");
    printf("Waits 2 seconds, then send a SIGTERM %i signal (it is blocked)\n",SIGTERM);
    sleep(2);
    kill(child,SIGTERM);
    printf("I sent it.\n");
  }
  else
  {
    sigemptyset(&sigset); //the child has a different addr-space
                          //so this won't affect the parent
    printf("I'm the child waiting for signal.\n");
    sigsuspend(&sigset);
    printf("Child process ended\n");

  }
  return 0;
}

See the man pages of the individual system functions for more information. You should be checking return codes too, even though most of these particular functions generally don't fail unless you call them wrong (some do, though, e.g., fork() can quite realistically fail if you're out of memory).