0

How can I get if a process receives a signal? The purpose of the following example is to fork a process, read a character with the child process and send SIGUSR1 to parent, but if after 10 seconds the user still have to insert the character, the child process is terminated. The question is how to know if SIGUSR1 is received:

#define _POSIX_SOURCE

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

void handle_USR1()
{
    return;
}

int main(void)
{
    int p[2];
    pid_t pid;

    if(pipe(p) == -1)
    {
        perror("pipe");
        return -1;
    }

    if((pid = fork()) == -1)
    {
        perror("fork");
        return -1;
    }

    if(pid == 0)
    {
        close(p[0]);
        char ch, b;

        ch = getchar();

        if(ch != '\n')
            while((b = getchar()) != '\n' && b != EOF);

        write(p[1], &ch, 1);
        kill(getppid(),SIGUSR1);

        exit(-1);
    }
    else
    {
        signal(SIGUSR1,handle_USR1);
        close(p[1]);
        char ch;

        sleep(10);
        kill(pid, SIGTERM);

        read(p[0],&ch,1);

        //if(/*SIGUSR1 is not recived*/)
        //{
        //    exit(-1);
        //}

        printf("\n\n%c",ch);
    }

    return 0;
}

What can I replace /*SIGUSR1 is not recived*/ with?

untitled
  • 389
  • 4
  • 13
  • 6
    Your `handle_USR1()` function should set a `static volatile sig_atomic_t` variable to a known value (e.g. 1). You can then check that variable to know whether a signal has been received. In Standard C, there's very little else that you can do in a signal handler in a strictly conforming way; in POSIX, you may do considerably more (but be careful: [Avoid using `printf()` in a signal handler](http://stackoverflow.com/questions/16891019/how-to-avoid-using-printf-in-a-signal-handler/) may help you. – Jonathan Leffler Feb 06 '16 at 20:39
  • Ok, so there aren't Standard C functions to do that, right? – untitled Feb 06 '16 at 20:54
  • 3
    @SimoneBonato No, but why should there be one? Jonathan Leffler's approach is perfectly fine and the way things are usually done. – fuz Feb 06 '16 at 21:00

2 Answers2

3

In a comment, I suggested:

Your handle_USR1() function should set a static volatile sig_atomic_t variable to a known value (e.g. 1). You can then check that variable to know whether a signal has been received. In Standard C, there's very little else that you can do in a signal handler in a strictly conforming way; in POSIX, you may do considerably more (but be careful: Avoid using printf() in a signal handler may help you).

Here's what I meant translated into code, closely based on your code:

sigusr1.c

#define _POSIX_SOURCE

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>

static volatile sig_atomic_t sig = 0;

static void handle_USR1(int signum)
{
    sig = signum;
}

int main(void)
{
    int p[2];
    pid_t pid;

    signal(SIGUSR1, handle_USR1);

    if (pipe(p) == -1)
    {
        perror("pipe");
        return -1;
    }

    if ((pid = fork()) == -1)
    {
        perror("fork");
        return -1;
    }

    if (pid == 0)
    {
        close(p[0]);
        char ch, b;

        ch = getchar();

        if (ch != '\n')
            while ((b = getchar()) != '\n' && b != EOF)
                ;

        write(p[1], &ch, 1);
        kill(getppid(), SIGUSR1);

        exit(-1);
    }
    else
    {
        close(p[1]);
        char ch;

        sleep(10);
        if (sig != 0)
            printf("Signal number %d received while sleeping\n", sig);
        else
        {
            printf("Sending SIGTERM to child %d\n", (int)pid);
            kill(pid, SIGTERM);
        }

        if (read(p[0], &ch, 1) == 1)
            printf("Character sent by child: [%c]\n", ch);
        else
            printf("No data sent by child before it died\n");
    }

    return 0;
}

Compilation

GCC 5.3.0 on Mac OS X 10.11.3 El Capitan:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror sigusr1.c -o sigusr1
$

Sample outputs

$ ./sigusr1
Sending SIGTERM to child 70657
No data sent by child before it died
$ ./sigusr1
Kaput
Signal number 30 received while sleeping
Character sent by child: [K]
$
Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • You might note that if the child gets no data (because the user types Control-D, for example, or standard input is redirected from `/dev/null`), then the child does not properly handle that and sends 0xFF to the parent. I'm not going to fix that — but caution is always appropriate. – Jonathan Leffler Feb 06 '16 at 21:50
0

Please chek man 2 signal which gives following synopsis

#include <signal.h>

   typedef void (*sighandler_t)(int);

   sighandler_t signal(int signum, sighandler_t handler);

You use signal to register your handler, the handler is of type

 void handler(int signum) {
     //do whatever you like
 }

Here the param sugnum receives the signal number. In your case it SIGUSR1 and can be inside the handle to determine which signal it is

dlmeetei
  • 9,905
  • 3
  • 31
  • 38