From fef712f9cfa27327c7eb3adbd1680b10eb4875a6 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Sat, 7 Mar 2026 22:42:41 +0000 Subject: [PATCH] docs: update Pending Signals documentation - Document the use of PTRACE_PEEKSIGINFO (kernel v3.10+) for dumping - Explain the distinction between shared and private pending signals - Detail the batch processing of signal queues - Explain the usage of rt_sigqueueinfo and rt_tgsigqueueinfo for restoration - Clarify the importance of PTRACE_GETSIGMASK Signed-off-by: Andrei Vagin --- .../under-the-hood/pending-signals.md | 34 +++++++++++++++---- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/Documentation/under-the-hood/pending-signals.md b/Documentation/under-the-hood/pending-signals.md index d4ec4c062..57499940d 100644 --- a/Documentation/under-the-hood/pending-signals.md +++ b/Documentation/under-the-hood/pending-signals.md @@ -1,12 +1,34 @@ # Pending Signals -### Introduction -A process can block a set of signals, causing them to wait in two kernel queues: one shared between threads and another private to each thread. Signals in these queues are referred to as "pending signals." Each signal includes a `siginfo` message, and several different types of `siginfo` exist. +In Linux, a signal is marked as **pending** if it has been delivered to a task but has not yet been handled (e.g., because the signal is blocked or the task is currently stopped). CRIU provides full support for capturing and restoring these pending signal queues, ensuring that the application's signal state remains perfectly consistent across a checkpoint. -### Dumping Pending Signals +## Checkpoint and Restore of Pending Signals -Dumping pending signals requires capturing the `siginfo` for each signal during a dump and then restoring it later. While this sounds simple, several challenges exist. First, the kernel traditionally does not report complete `siginfo` structures to userspace; for example, it often strips the `SI_CODE` field in signal handlers. Additionally, `siginfo` received via a `signalfd` uses a different format with fixed-size fields. +CRIU manages pending signals using specialized `ptrace` interfaces and signal injection system calls. -To address this, the `signalfd` interface was extended. When created with the `SFD_RAW` flag, `signalfd` returns `siginfo` in its raw format. Furthermore, the `SFD_GROUP` and `SFD_PRIVATE` flags were added to allow selecting the specific queue to dump. +### 1. Checkpointing (Dumping) +During a dump, CRIU must extract both the list of pending signals and the detailed metadata associated with each one (the `siginfo_t` structure). -Once signals are captured, they must be restored. While `rt_sigqueueinfo` is suitable for this, it traditionally cannot send `siginfo` with a positive `si_code`, as those values are reserved for the kernel. However, since a process should have the right to manage its own state, it should be able to send any `siginfo` to itself during restoration. +* **PTRACE_PEEKSIGINFO**: CRIU uses this system call (introduced in Linux kernel v3.10 specifically to support CRIU) to read the signal queues of the target task without actually delivering them. + * **Private Signals**: Signals delivered to a specific thread are read using standard peeking. + * **Shared Signals**: Signals delivered to the entire process (which can be handled by any thread) are read by adding the `PTRACE_PEEKSIGINFO_SHARED` flag. +* **Batch Processing**: CRIU reads signals in batches (typically 32 at a time) to efficiently capture entire queues, which is common in high-throughput applications. +* **Signal Mask**: In addition to the pending signals, CRIU uses `PTRACE_GETSIGMASK` to capture the set of signals currently blocked by each thread. This mask is essential because it determines why the signals were pending in the first place. + +### 2. Restoration +To recreate the pending state, CRIU re-injects the captured signals into the newly created process tree before it begins normal execution. + +* **rt_sigqueueinfo()**: For process-wide (shared) signals, CRIU uses this system call to send a signal to a process with the original `siginfo_t` data. +* **rt_tgsigqueueinfo()**: For thread-specific (private) signals, CRIU uses this variant to target a specific thread ID (TID) within a process. +* **Preserving siginfo**: These system calls allow CRIU to pass the exact original `siginfo_t` structure (including the sender's PID, UID, and any signal-specific data), ensuring the restored task sees the identical signal context. + +## Shared vs. Private Pending Signals + +* **Multi-threaded Handling**: In multi-threaded applications, signals are carefully tracked: + * **Shared signals** are stored in the process leader's `core.img`. + * **Private signals** are stored in the `core.img` corresponding to each individual thread. +* **Restore Order**: Signals are restored while the task is still under CRIU's control, ensuring that they remain pending until the task is finally resumed and its original signal mask is applied. + +## See also +* [Checkpoint/Restore Architecture](checkpointrestore.md) +* [Parasite Code](parasite-code.md)