Home > other >  How to fix signal handler functions are never invoked in c?
How to fix signal handler functions are never invoked in c?

Time:05-29

In the following code, I try to send SIGINT, SIGHUP, SIGQUIT signal to child process.

void sighup(int sig); void sigint(int sig); void sigquit(int sig); These are my signal handler.

the issue is signal handler never invoked.

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

void sighup(int sig);
void sigint(int sig);
void sigquit(int sig);
int main()
{
    int pid, i, j, k;
    if ((pid = fork()) < 0)
    {
        perror("fork");
        exit(1);
    }
    if(pid == 0)
    {

        signal(SIGHUP, sighup);
        signal(SIGINT, sigint);
        signal(SIGQUIT, sigquit);
    }
    else
    {
        j = 0;
        for (i = 1; i <= 5; i  )
        {
            j  ;
            if (i % 2 == 0)
            {
                printf("PARENT: sending SIGHUP Signal : %d\n", j);
                kill(pid, SIGHUP);
                sleep(3);
            }
            else
            {
                printf("PARENT: sending SIGINT signal : %d\n", j);
                kill(pid, SIGINT);
                sleep(3);
            }
        }
        printf("Parent sending SIGQUIT\n");
        kill(pid, SIGQUIT);

    }
}
void sighup(int sig)
{
    signal(SIGHUP, sighup);
    printf("Child: I have received sighup\n");
}
void sigint(int sig)
{
    signal(SIGINT, sigint);
    printf("Child: I have received sighINT\n");
}
void sigquit(int sig)
{
    printf("My daddy has killed me\n");
    exit(0);
}

Below lines never printed on screen

Child: I have received sighup Child: I have received sighINT My daddy has killed me

Output

PARENT: sending SIGINT signal : 1
PARENT: sending SIGHUP Signal : 2
PARENT: sending SIGINT signal : 3
PARENT: sending SIGHUP Signal : 4
PARENT: sending SIGINT signal : 5
Parent sending SIGQUIT

CodePudding user response:

You have two problems here.

First, after the child process sets up its signal handlers, it exits right away. So the parent might get to send the first signal depending on timing, but not any others.

Put the child in a pause loop to have it wait for signals.

The other problem is that it's possible that the parent might send the first signal to the child before it can set up its signal handlers. So put a short delay in the parent to allow that to happen.

if(pid == 0)
{
    signal(SIGHUP, sighup);
    signal(SIGINT, sigint);
    signal(SIGQUIT, sigquit);
    while (1) pause();
}
else
{
    sleep(1);
    ...

Also, calling printf and exit from a signal handler are not considered safe. It's better to have the signal handlers set a global variable and have the main part of the code check for that.

int gotsig = 0;

void sighup(int sig)
{
    signal(SIGHUP, sighup);
    gotsig = sig;
}
void sigint(int sig)
{
    signal(SIGINT, sigint);
    gotsig = sig;
}
void sigquit(int sig)
{
    gotsig = sig;
}

...
    while (1) {
        pause();
        if (gotsig == SIGHUP) {
            printf("Child: I have received sighup\n");
        } else if (gotsig == SIGINT) {
            printf("Child: I have received sighINT\n");
        } else if (gotsig == SIGQUIT) {
            printf("My daddy has killed me\n");
            exit(0);
        }
        gotsig = 0;
    }

CodePudding user response:

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
void signint(int sig);
void sighup(int sig);
void sigquit(int sig);

int gotsig;

int main()
{
    int pid,i;
    pid = fork();
    if(pid < 0)
    {
        perror("fork");
        exit(0);
    }

    if(pid == 0)
    {
        signal(SIGHUP,sighup);
        signal(SIGINT,signint);
        signal(SIGQUIT,sigquit);

        pause();
        while(1)
        {
            if(gotsig == SIGINT)
            {
                printf("Child : Child process recieved SIGINT signal\n");
                gotsig = -1;
            }else if(gotsig == SIGHUP)
            {
                printf("Child : Child process recieved SIGHUP signal\n"); 
                gotsig = -1;
            }else if(gotsig == SIGQUIT)
            {
                printf("Dady killed me....!\n");
                exit(0);
            }
        }
    }else
    {
        sleep(1);
        for(i = 1; i <=5 ; i  )
        {
            if(i % 2 == 0)
            {
                printf("Parent : sending SIGINT signal\n");
                kill(pid,SIGINT);
                sleep(3);
            }else
            {
                printf("Parent : sending SIGHUP signal\n");
                kill(pid,SIGHUP);
                sleep(3);
            }
        }
        printf("Parent : sending SIGQUIT signal\n");
        kill(pid,SIGQUIT);
    }
}

void signint(int sig)
{
    gotsig = sig;
}

void sighup(int sig)
{
    gotsig = sig;
}

void sigquit(int sig)
{
    gotsig = sig;
}

Above code work fine for me.

Output :

Parent : sending SIGHUP signal
Child : Child process recieved SIGHUP signal
Parent : sending SIGINT signal
Child : Child process recieved SIGINT signal
Parent : sending SIGHUP signal
Child : Child process recieved SIGHUP signal
Parent : sending SIGINT signal
Child : Child process recieved SIGINT signal
Parent : sending SIGHUP signal
Child : Child process recieved SIGHUP signal
Parent : sending SIGQUIT signal
Dady killed me....!
  • Related