How to Tell in Linux Which Process Sent My Process a Signal

How can I tell in Linux which process sent my process a signal

Two Linux-specific methods are SA_SIGINFO and signalfd(), which allows programs to receive very detailed information about signals sent, including the sender's PID.

  • Call sigaction() and pass to it a struct sigaction which has the desired signal handler in sa_sigaction and the SA_SIGINFO flag in sa_flags set. With this flag, your signal handler will receive three arguments, one of which is a siginfo_t structure containing the sender's PID and UID.

  • Call signalfd() and read signalfd_siginfo structures from it (usually in some kind of a select/poll loop). The contents will be similar to siginfo_t.

Which one to use depends on how your application is written; they probably won't work well outside plain C, and I wouldn't have any hope of getting them work in Java. They are also unportable outside Linux. They also likely are the Very Wrong Way of doing what you are trying to achieve.

Finding the process which sent signal in c

You set up your signal handler with sigaction using the SA_SIGINFO flag. Your handler will accept a parameter of siginfo_t. Within the siginfo_t struct is the field si_pid. This is the process id of the sending process. Match that against the child's ppid().

What order are signals sent to a process group in Linux?

I've been browsing the Linux kernel source and I think I have the answer. When sending a signal via kill, Linux iterates over the linked list held in the pid structure, which contains all the tasks that use that PID. I believe that this means it iterates over processes in a group in the reverse order they were forked() as the PID is added to the linked list with hlist_add_head_rcu, which inserts it at the head. I don't think this behavior should be relied on though, as they could change it in several ways.

Linux C: upon receiving a signal, is it possible to know the PID of the sender?

Yes, if you use the sigaction() call to set up your signal handler instead of signal. Doing so will let you set up a signal handler that takes three parameters:

  • An int, for the signal number (just like signal)
  • A siginfo_t *, which is a structure containing all sorts of information about the source of the signal, including the pid of the sender if applicable. (It also includes some information about the cause of the signal for automatic signals like SIGSEGV.)
  • A ucontext_t *, which has to do with which thread got the signal. Mostly ignorable.

When several signals arrive at a process, what is the order between the process handling the signals?

SIGCONT has special semantics.

Regardless of whether SIGCONT is caught, is ignored, or has default disposition, its generation will clear all pending stop signals and resume execution of a stopped process. [IEEE Std 1003.1-2017] Again, this resumption happens before any other signals are delivered, and even before SIGCONT's handler (if any) is invoked.

(This special “dispositionless” semantic makes sense. In order for a process to execute a signal handler, the process must itself be executing.)

POSIX is clearer than APUE here, saying that "[t]he default action for SIGCONT is to resume execution at the point where the process was stopped, after first handling any pending unblocked signals."

As others have mentioned, the actual order in which pending signals are delivered is implementation-specific. Linux, at least, delivers basic UNIX signals in ascending numeric order.

To demonstrate all this, consider the following code. It STOPs a process, then sends it several signals, then CONTinues it, having installed handlers for all catchable signals so we can see what is handled when:

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

static int signals[] = { SIGSTOP, SIGURG, SIGUSR1, SIGHUP, SIGCONT, 0 };

static void
handler(int signo) {
// XXX not async-signal-safe
printf("<signal %d>\n", signo);
}

int
main(int argc, char **argv) {
int *sig = signals;
struct sigaction sa = { .sa_flags = 0, .sa_handler = handler };

sigfillset(&sa.sa_mask);

sig++; // can't catch SIGSTOP
while (*sig) {
sigaction(*sig, &sa, NULL); // XXX error check
sig++;
}

if (fork() == 0) { // XXX error check
sleep(2); // faux synchronization - let parent pause()

sig = signals;
while (*sig) {
printf("sending signal %d\n", *sig);
kill(getppid(), *sig);
sig++;
}
exit(0);
}

pause();

return 0;
}

For me, this prints

sending signal 19
sending signal 23
sending signal 10
sending signal 1
sending signal 18
<signal 1>
<signal 10>
<signal 18>
<signal 23>


Related Topics



Leave a reply



Submit