Linux C: after receiving the signal, is it possible to find out the sender ID?

Suppose my program C processes SIGUSR1. When he receives a signal, is it possible to find out who sent it? I.e,. get the pid of this process?

+15
c linux signals system
Jul 16 '12 at 16:21
source share
3 answers

Yes, if you use the sigaction call to configure your signal handler instead of signal . This will allow you to configure a signal handler that accepts three parameters:

  • An int , for the signal number (exactly the same as signal )
  • A siginfo_t * , which is a structure containing all kinds of information about the signal source, including the pid of the sender, if applicable. (It also contains some information about the signal reason for automatic signals like SIGSEGV .)
  • A ucontext_t * , which is associated with which stream received the signal. Mostly ignored.
+15
Jul 16 2018-12-16T00:
source share

Yes. Register a signal handler using sigaction with the SA_SIGINFO flag, filling in the sa_sigaction field. Now your handler function accepts the siginfo_t* parameter, which includes the si_pid field.

Please note that si_pid set only in certain circumstances. In your case, you need to check that si_code set to SI_USER or SI_QUEUE . Read more about man 2 sigaction .

+10
Jul 16 2018-12-16T00:
source share

Another option is signalfd() . If you use signals to transfer information between processes, then a more structured signal processing than signal handlers is most likely what you want. struct signalfd_siginfo::ssi_pid - sender.

Example from the man page:

 #include <sys/signalfd.h> #include <signal.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #define handle_error(msg) \ do { perror(msg); exit(EXIT_FAILURE); } while (0) int main(int argc, char *argv[]) { sigset_t mask; int sfd; struct signalfd_siginfo fdsi; ssize_t s; sigemptyset(&mask); sigaddset(&mask, SIGINT); sigaddset(&mask, SIGQUIT); /* Block signals so that they aren't handled according to their default dispositions */ if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1) handle_error("sigprocmask"); sfd = signalfd(-1, &mask, 0); if (sfd == -1) handle_error("signalfd"); for (;;) { s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo)); if (s != sizeof(struct signalfd_siginfo)) handle_error("read"); if (fdsi.ssi_signo == SIGINT) { printf("Got SIGINT\n"); } else if (fdsi.ssi_signo == SIGQUIT) { printf("Got SIGQUIT\n"); exit(EXIT_SUCCESS); } else { printf("Read unexpected signal\n"); } } } 

See also: sigqueue() . Like kill() , but you can pass an integer or pointer in the same call.

+3
Mar 28 '17 at 12:54 on
source share



All Articles