clinuxsignalssignal-handlingsignalhandler

Can we send parameters to a signal handler using sigaction?


I notice that sigaction has a alternate signal handler that is called when the SA_SIGINFO flag is set. The alternate function has a void* context parameter. Now, according to the APUE book, this parameter can be cast into a ucontext_t structure. My question is that can I not cast it into any structure of my choice ? That way I could pass my own arguments into a signal handler. I noticed a post in stackoverflow stating that we just can't pass arguments to a signal handler as they are a very primitive feature. Is this possible ?


Solution

  • Yes, you can pass user-supplied data to a signal handler - but not by using the context argument. Instead, you have to use sigqueue(3) to raise a signal with a handler installed with SA_SIGINFO. This populates either the si_int or si_ptr field of the siginfo_t structure that is the handler's second argument, depending on sigqueue()'s third argument.

    Example:

    #include <signal.h>
    #include <string.h>
    #include <unistd.h>
    
    void usr1_handler(int signo, siginfo_t *info, void *context) {
      const char *msg = info->si_ptr;
      write(STDOUT_FILENO, msg, strlen(msg));
    }
    
    int main(void) {
      struct sigaction sa;
      sa.sa_sigaction = usr1_handler;
      sigemptyset(&sa.sa_mask);
      sa.sa_flags = SA_SIGINFO;
      sigaction(SIGUSR1, &sa, NULL);
    
      const char *msg = "SIGUSR1 was called.\n";
      sigqueue(getpid(), SIGUSR1, (union sigval){ .sival_ptr = (void *)msg });
    
      return 0;
    }
    

    (Real code will include error checking and handling, of course).

    When compiled and run, this toy program will print SIGUSR1 was called..