Question

I'm studying C signals and I'm having trouble with an exercise that requires to write a program which sends back any signal it receives from a process back to the sender process. I thought about using the function signal() or the function sigaction(), but they ask you to specify the signum, and I would need them to handle EVERY signal my program receives. Is there any way to do so without calling the sigaction() for every signal number? Thank you in advance for your answers

Was it helpful?

Solution

You don't specify what OS you are using but this is simple on POSIX systems. I can't speak to Windows.

The call you want is sigwaitinfo.

You need to block all signals and then use sigwaitinfo to process any received signals synchronously. Sigwaitinfo's return code is the signal received and when you pass a non-null siginfo_t struct as the second parameter you get the same information you would get from a signal handler returning a siginfo_t structure, including the pid of the sending process. Take the received signal and pid and use kill to send the signal back to the originating process. Make sure you aren't sending the signal to yourself before calling kill lest you end up in a loop of sending and receiving a signal to yourself.

#define _POSIX_C_SOURCE 200809L

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

#define errExit(msg) do {perror(msg); exit(EXIT_FAILURE);} while (0)

int main(int argc, char *argv[])
{
    siginfo_t signalInfo;
    sigset_t  allSignals;

    printf("echo pid = %d\n", getpid());

    // block every signal but SIGKILL & SIGSTOP which can't be blocked
    sigfillset(&allSignals);

    if (sigprocmask(SIG_SETMASK, &allSignals, NULL) == -1)
        errExit("sigprocmask");

    while(1)
    {
        // accept signals until SIGTERM delivered
        int sig = sigwaitinfo(&allSignals, &signalInfo);

        if (sig == -1)
            errExit("sigwaitinfo");

        if (sig == SIGTERM)
        {
            printf("buh-bye\n");
            exit(EXIT_SUCCESS);
        }

        printf("echo received signal %s (%d) from pid = %d\n", strsignal(sig), sig, signalInfo.si_pid);

        /*** NOT doing this for testing because it will kill the sending shell

        // echo signal back to sender but not to yourself
        // which would be stupid and lead to an endless loop

        if (signalInfo.si_pid != getpid())
            kill(signalInfo.si_pid, sig);

       ***/
    }
}

TEST

--- terminal 1 ---

//current shell's pid
> echo $$
7646
//send signals after starting echo pgm in another terminal
> kill -SIGUSR1 7754
> kill -SIGUSR2 7754
> kill -SIGTERM 7754

--- terminal 2 ---

> echosig 
echo pid = 7754
echo received signal User defined signal 1 (10) from pid = 7646
echo received signal User defined signal 2 (12) from pid = 7646
buh-bye
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top