简体   繁体   中英

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?

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. .

From this sigaction manual page :

This is a pointer to a ucontext_t structure, cast to void * . The structure pointed to by this field contains signal context information that was saved on the user-space stack by the kernel; ... Commonly, the handler function doesn't make any use of the third argument.

So this argument is a kernel-specific pointer to a special signal context. It's not possible to reuse it for user-data.

Another important thing that I noticed about passing parameters to signal handlers is that, the entire concept of being able to pass an additional parameter to a signal handler does not make any sense. A signal handler is something that is not explicitly called by the programmer. Instead it is something that is called asynchronously when the kernel sends a signal to the program. Now, even if it were possible to pass an additional argument to a signal handler, what would determine which argument is to be sent? Say the signal handler has a prototype of void func(int, void*); . How would the application know which argument should be passed to the second parameter? It would be a completely indeterminate situation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM