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

怎甘沉沦 提交于 2019-12-11 10:32:42

问题


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

What data structure is used to store the signals which have arrived at a process but not yet been delivered?

For example, from APUE

Since the process group is orphaned when the parentterminates, POSIX.1 requires that every process in the newly orphaned process group that is stopped (as our child is) be sent the hang-up signal (SIGHUP) followed by the continue signal (SIGCONT)

This causes the child to be continued, after processing the hang-up signal. The default action for the hang-up signal is to terminate the process, so we have to provide a signal handler to catch the signal. We therefore expect the printf in the sig_hup function to appear before the printf in the pr_ids function.

As https://stackoverflow.com/a/17769300/156458 says

The SIGHUP cannot be delivered until the child's execution is resumed. When a process is stopped, all signal delivery is suspended except for SIGCONT and SIGKILL.

So, the SIGHUP does arrive first, but it cannot be processed until the SIGCONT awakens the process execution.

SIGHUP arrives before SIGCONT at a stopped process. SIGHUP can't be delievered while SIGCONT can be.

Is SIGCONT handled before or after SIGHUP? The first quote seems to say "after", while the second quote seems to say "before" by "until".

If "before":

  • How can SIGCONT be arranged to jump ahead of SIGHUP to be delivered?

  • How can SIGHUP not be discarded when SIGCONF jumps before it to be delievered?

Are the above implemented based on some data structures such as FIFO queue or FILO stack?

Thanks.


回答1:


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>



回答2:


The situation is probably confused by different implementations and by the introduction of POSIX real time signals. http://man7.org/linux/man-pages/man7/signal.7.html says that real-time signals are distinguished from old style signals by

Real-time signals are delivered in a guaranteed order. Multiple real-time signals of the same type are delivered in the order they were sent. If different real-time signals are sent to a process, they are delivered starting with the lowest-numbered signal. (I.e., low-numbered signals have highest priority.) By contrast, if multiple standard signals are pending for a process, the order in which they are delivered is unspecified.

As of the old style signals described in "The Design of the Unix Operating System" by Bach (before the introduction of POSIX real-time signals).

To send a signal to a process, the kernel sets a bit in the signal field of the process table entry, corresponding to the type of signal received. ... the kernel checks for receipt of a signal when the process returns from kernel mode to user mode and when it leaves the sleep state at a suitably low signalling priority.

You can see some of the current linux data structures at https://github.com/torvalds/linux/blob/master/include/linux/sched.h. Looking at this I suspect that the old-style bitmap has gone, and a combination of bitmap and linked list is used to handle both old style and POSIX real time signals, but I have not gone through enough of the code to be sure of this.




回答3:


To add to mcdowella's response:

1) The specifics of "signal handling" can vary from platform to platform

2) In the specific case of Linux:

http://man7.org/linux/man-pages/man7/signal.7.html

Linux supports both POSIX reliable signals (hereinafter "standard signals") and POSIX real-time signals.

3) See also:

  • About the delivery of standard signals

  • Why Linux decides that standard signals have higher priority than rt-signals?

  • The Linux Kernel - Signals


来源:https://stackoverflow.com/questions/50635458/when-several-signals-arrive-at-a-process-what-is-the-order-between-the-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!