0

I'm trying to send the child process a blank(SIGUSR1) signal from the parent. As far as I know, I have the signal set up properly. I feel like I am messing up on the Kill() function call. I expect some sort of printed output, but I get nothing. Not from inside the child nor from the signal function itself.

code:

void my_handler(int signum);

int main()
{
  pid_t pid;

  if((pid = fork()) == -1)
  {
    printf("Error on fork().\n");
    exit(1);
  }

  if(pid == 0)
  {
    if(signal(SIGUSR1, my_handler))
    {
     printf("+1"); 
    }
  }
  else if(pid > 0)
  {
    sleep(2);
    kill(pid, SIGUSR1);
  }

}

void my_handler(int signum)
{
    if (signum == SIGUSR1)
    {
        printf("Received SIGUSR1!\n");
    }
}
Andrew Ricci
  • 475
  • 5
  • 21
  • 1
    Do yourself a favour: check the return values from system calls, such as `kill()`. They tell you whether the system thinks the call worked or not. – Jonathan Leffler Oct 14 '15 at 22:28
  • Your child process is exiting as soon as it has installed the signal handler. It does not wait to receive the signal. – kaylum Oct 14 '15 at 22:31
  • `printf()` is not async-signal-safe and should never be called from a signal handler. Read the "**Async-signal-safe functions**" section: http://man7.org/linux/man-pages/man7/signal.7.html – Andrew Henle Oct 14 '15 at 23:46

2 Answers2

3

The child process exits before the parent process has a chance to send a signal to it. Try adding sleep(5) in the child process after calling signal.

Adrian
  • 14,931
  • 9
  • 45
  • 70
2

You child exits before the signal is sent:

  if(pid == 0)
  {
    if(signal(SIGUSR1, my_handler))
    {
     printf("+1"); 
    }
  }
  else if(pid > 0)
  {
    sleep(2);
    kill(pid, SIGUSR1);
  }

The child might print +1, but then it exits. Meanwhile, your parent waits two seconds to make sure the child is really dead, and then sends it a signal. It isn't there!

To fix: Add some sort of code that makes the child hang around to receive the signal. The simplest is probably pause();, though a sleep() for more than 2 seconds would work.

You should check your system calls. For example:

if (kill(pid, SIGUSR1) != 0)
{
    fprintf(stderr, "kill(%d) failed: %d %s\n", (int)pid, errno, strerror(errno));
    exit(1);
}

You quickly get fed up with writing 4 lines of code so you end up with a function that reports a system error and exits (using C11 _Noreturn):

void _Noreturn err_syserr(const char *fmt, ...)
{
    int errnum = errno;  // Capture it before it changes
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errno != 0)
        fprintf(stderr, "%d: %s\n", errnum, strerror(errnum));
    exit(1);
}

Use:

if (kill(pid, SIGUSR1) != 0)
    err_syserr("kill(%d) failed: ", (int)pid);

(Not everyone agrees with printing the error number; you pay your money and take your pick.)

See also How to avoid using printf in a signal handler? It isn't a part of your problem, but you should be aware of the issues.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278