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