Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't my signal handler being called?

Im working on a assignment which uses signals to transfer a binary message between two processes, with the goal of learning about signals (it is a strange use indeed).

In my program, the two processes communicate a code, and then one transfers a message to the other. SIGUSR1 represents 0, SIGUSR2 represents 1. The idea is that the process sending the message will use the kill function with whichever SIGUSR to get the message across, and the receiving process will have a signal handler to interpret the codes.

So here is the problem. I have the sender start up. it sleeps while it waits for the code to be sent. The reciever sends two SIGINT's to signify the 'password', using pidof(8) to find the pid of the sender.

Once the sender's signal handler has read these signals, recognizes it is the proper password, it then proceeds to send the message.

The reciever has now gone through a few functions, and is sleeping every second waiting for each bit to be passed via an interrupt. The problem is, this never happens.

I have set it up such that the sender is sending a bit(0 in this case) like so:

kill(washingtonPID,SIGUSR1);

where washingtonPID is the PID of the receiver, and I have verified this is the correct PID.

the receiver's handler is hooked up like so:

//IN MAIN
    signal(SIGINT,bitReceiver);
    signal(SIGUSR1,bitReceiver);
    signal(SIGUSR2,bitReceiver);
//OUTSIDE MAIN

    void bitReceiver(int signum)
{
    if(signum == SIGUSR1)
    {
        fprintf(stderr,"SIGUSR1 - 0");
        bit = 0;
    }
    else if (signum == SIGUSR2)
    {
        fprintf(stderr,"SIGUSR2 - 1");
        bit = 1;
    }
    else //sigint
    raise(SIGINT);

    return;
}

where bit is a global variable. it is initially set to -1.

Here is the function which reads the bits:

 int receiveBit()
{
    while(bit == -1)
    {
        sleep(1);
    }
    fprintf(stderr,"%d",bit);
    int bit2 = bit;
    bit = -1;
    return bit2;
}

So the basic run through is this: After the code has been sent from the receiver to the sender, the sender starts to send kill signals of USR1 and USR2 to the receiver, which should eventually form a binary message.

The receiver is simply waiting at this point, sleeping every second. When it gets interrupted, the handler will set bit to 0 or 1, kicking it out of sleep, printing the bit, and returning it.

If i let the two programs run normally, the reciever just sits in sleep, and the handler is never called (even though I can see the calls being made by the other process.

If i stop the sender, and manually send the Kill signals, i can send one, maybe two signals, both handled properly. any after that, and I get a message printed to the terminal like 'user signal 2'. Which is not something I have in my program, and the program immediately stops.

Any insights as to why my handler isn't being envoked, and why I can't manually send more then one or two signals would be greatly appreciated.

Thanks for your time.

EDIT: It seems like people are stumped on this. Are there any debugging tips I could try?

like image 230
Blackbinary Avatar asked Feb 05 '11 16:02

Blackbinary


People also ask

Does Sigaction call the signal handler?

sigaction() can be called with a NULL second argument to query the current signal handler. It can also be used to check whether a given signal is valid for the current machine by calling it with NULL second and third arguments.

Does signal () call the signal handler?

signal() sets the disposition of the signal signum to handler, which is either SIG_IGN, SIG_DFL, or the address of a programmer- defined function (a "signal handler"). If the signal signum is delivered to the process, then one of the following happens: * If the disposition is set to SIG_IGN, then the signal is ignored.

Where are signal handlers executed?

Most handlers run on the thread's stack. A handler can run on an alternate stack if the process uses sigaltstack(2) to provide the stack, and sigaction(2) with SA_ONSTACK to set the handler.

Do signal handlers run concurrently?

Signal handlers run concurrently with main program (in same process).


1 Answers

As many have already commented, you shouldn't be doing this with signals at all. When it goes wrong (and it will, like it did) trying to find out what is wrong when undefined behaviour is behind it is hard if not impossible.

Using non async-safe system calls like fprintf inside signal handlers can corrupt the data since fprintf is operating on the same stream. Same with shared variables.

Since you are using linux, signals of the same type will not be blocked, meaning that rapid delivery of the same signal can result in recursive call to the handler. Once a signal is caught, the disposition of the signal is reset to SIG_DFL and needs to be reestablished in the handler again (which can also fail if the signal is delived before it has the change to be reestablished).

That is why you can send a maximum of 1 signal of the same type before the signal gets reset to default and terminated the program with "user signal xx".

I would recommend you stop tormenting yourself with the code and grab some textbook or a tutorial and try to follow that.

Signal call should also be avoided if it goes. From the man pages:

The behavior of signal() varies across UNIX versions, and has also varied historically across different versions of Linux. Avoid its use: use sigaction(2) instead.

like image 119
Milan Avatar answered Oct 13 '22 01:10

Milan