Signal Numbers and Sets
Relevant source files
This document details the signal numbers and signal sets implementation in the axsignal crate, which provides the foundation for signal handling in ArceOS. For information about signal actions and handling, see Signal Actions and Dispositions. For information about pending signal management, see Pending Signals.
Overview
The signal system in axsignal implements Unix-compatible signal numbers and sets that are used throughout the signal handling framework. Signal numbers (represented by the Signo enum) identify specific signals, while signal sets (represented by the SignalSet struct) provide an efficient way to manage collections of signals.
flowchart TD
subgraph subGraph1["Usage in System"]
TSM["ThreadSignalManager"]
PSM["ProcessSignalManager"]
PS["PendingSignals"]
SA["SignalAction"]
end
subgraph subGraph0["Signal Numbers and Sets"]
Signo["Signo Enum"]
SignalSet["SignalSet Struct"]
end
SignalSet --> PS
SignalSet --> PSM
SignalSet --> TSM
Signo --> PS
Signo --> SA
Sources: src/types.rs(L9 - L182)
Signal Numbers (Signo)
The Signo enum defines all standard Unix signals and real-time signals. It is implemented as a u8 enum with explicit numeric values that correspond to standard Unix signal numbers.
Signal Categories
Signal numbers in axsignal are divided into two main categories:
- Standard Signals (1-31): Traditional Unix signals with predefined behaviors
- Real-time Signals (32-64): Extended signals for application-defined purposes
classDiagram
class Signo {
<<enum>>
SIGHUP = 1
SIGINT = 2
...
SIGSYS = 31
SIGRTMIN = 32
...
SIGRT32 = 64
is_realtime() bool
default_action() DefaultSignalAction
}
class DefaultSignalAction {
<<enum>>
Terminate
CoreDump
Ignore
Stop
Continue
}
Signo --> DefaultSignalAction : returns
Sources: src/types.rs(L9 - L77) src/types.rs(L79 - L120)
Standard Signals
Standard signals (1-31) represent traditional Unix signals, each with a specific purpose and default behavior:
| Signal Number | Name | Default Action | Description |
|---|---|---|---|
| 1 | SIGHUP | Terminate | Hangup detected on controlling terminal |
| 2 | SIGINT | Terminate | Interrupt from keyboard (Ctrl+C) |
| 3 | SIGQUIT | CoreDump | Quit from keyboard (Ctrl+) |
| 4 | SIGILL | CoreDump | Illegal instruction |
| 5 | SIGTRAP | CoreDump | Trace/breakpoint trap |
| 6 | SIGABRT | CoreDump | Abort signal |
| 7 | SIGBUS | CoreDump | Bus error |
| 8 | SIGFPE | CoreDump | Floating-point exception |
| 9 | SIGKILL | Terminate | Kill signal (cannot be caught or ignored) |
| 10 | SIGUSR1 | Terminate | User-defined signal 1 |
| 11 | SIGSEGV | CoreDump | Invalid memory reference |
| 12 | SIGUSR2 | Terminate | User-defined signal 2 |
| 13 | SIGPIPE | Terminate | Broken pipe |
| 14 | SIGALRM | Terminate | Timer signal |
| 15 | SIGTERM | Terminate | Termination signal |
| 16 | SIGSTKFLT | Terminate | Stack fault |
| 17 | SIGCHLD | Ignore | Child stopped or terminated |
| 18 | SIGCONT | Continue | Continue if stopped |
| 19 | SIGSTOP | Stop | Stop process (cannot be caught or ignored) |
| 20 | SIGTSTP | Stop | Stop typed at terminal (Ctrl+Z) |
| 21 | SIGTTIN | Stop | Terminal input for background process |
| 22 | SIGTTOU | Stop | Terminal output for background process |
| 23 | SIGURG | Ignore | Urgent condition on socket |
| 24 | SIGXCPU | CoreDump | CPU time limit exceeded |
| 25 | SIGXFSZ | CoreDump | File size limit exceeded |
| 26 | SIGVTALRM | Terminate | Virtual alarm clock |
| 27 | SIGPROF | Terminate | Profiling timer expired |
| 28 | SIGWINCH | Ignore | Window resize signal |
| 29 | SIGIO | Terminate | I/O now possible |
| 30 | SIGPWR | Terminate | Power failure |
| 31 | SIGSYS | CoreDump | Bad system call |
Sources: src/types.rs(L12 - L43) src/types.rs(L84 - L118)
Real-time Signals
Real-time signals (32-64) are numbered from SIGRTMIN (32) to SIGRT32 (64) and are primarily for application-defined purposes. Unlike standard signals, real-time signals:
- Have no predefined meanings
- Default to the
Ignoreaction - Are queued (multiple instances of the same signal can be pending)
flowchart TD
subgraph subGraph1["Default Actions"]
Terminate["Terminate Process"]
CoreDump["Terminate with Core Dump"]
Ignore["Ignore Signal"]
Stop["Stop Process"]
Continue["Continue Process"]
end
subgraph subGraph0["Signal Number Range"]
StandardSignals["Standard Signals (1-31)"]
RealTimeSignals["Real-time Signals (32-64)"]
end
RealTimeSignals --> Ignore
StandardSignals --> Continue
StandardSignals --> CoreDump
StandardSignals --> Ignore
StandardSignals --> Stop
StandardSignals --> Terminate
Sources: src/types.rs(L44 - L76) src/types.rs(L80 - L82) src/types.rs(L117 - L118)
Signo Implementation
The Signo enum provides two key methods:
is_realtime(): Determines if a signal is a real-time signal by checking if its value is greater than or equal toSIGRTMIN(32).
#![allow(unused)] fn main() { pub fn is_realtime(&self) -> bool { *self >= Signo::SIGRTMIN } }
default_action(): Returns the default action for a signal (as aDefaultSignalActionenum).
#![allow(unused)] fn main() { pub fn default_action(&self) -> DefaultSignalAction { match self { Signo::SIGHUP => DefaultSignalAction::Terminate, // ... other cases ... _ => DefaultSignalAction::Ignore, // For real-time signals } } }
Sources: src/types.rs(L79 - L120)
Signal Sets (SignalSet)
A SignalSet is a bit vector representation of a set of signals, compatible with the C sigset_t type. It provides an efficient way to represent and manipulate collections of signals.
Representation
The SignalSet is implemented as a transparent wrapper around a u64, where:
- Each bit position corresponds to a signal number minus 1
- Bit is set (1) if the signal is in the set
- Bit is clear (0) if the signal is not in the set
flowchart TD
subgraph subGraph0["SignalSet Representation"]
B1["Bit 0"]
S1["SIGHUP (1)"]
B2["Bit 1"]
S2["SIGINT (2)"]
B3["Bit 2"]
S3["SIGQUIT (3)"]
D["..."]
DS["..."]
B30["Bit 30"]
S31["SIGSYS (31)"]
B31["Bit 31"]
S32["SIGRTMIN (32)"]
B63["Bit 63"]
S64["SIGRT32 (64)"]
end
B1 --> S1
B2 --> S2
B3 --> S3
B30 --> S31
B31 --> S32
B63 --> S64
D --> DS
Sources: src/types.rs(L122 - L126)
Operations
The SignalSet struct provides several operations for manipulating signal sets:
- Adding a signal:
add(&mut self, signal: Signo) -> bool
- Sets the bit corresponding to the signal
- Returns true if the signal was not already in the set
- Removing a signal:
remove(&mut self, signal: Signo) -> bool
- Clears the bit corresponding to the signal
- Returns true if the signal was in the set
- Checking for a signal:
has(&self, signal: Signo) -> bool
- Returns true if the bit corresponding to the signal is set
- Dequeueing a signal:
dequeue(&mut self, mask: &SignalSet) -> Option<Signo>
- Finds and removes the lowest-numbered signal that is both in the set and in the mask
- Returns the removed signal, or None if no matching signal exists
- Bitwise operations: The struct implements
Not,BitOr,BitOrAssign,BitAnd, andBitAndAssign
- Allows combining and modifying signal sets using standard bit operations
flowchart TD
subgraph subGraph1["SignalSet Operations"]
A["Original Set"]
B["Modified Set"]
Result["Boolean Result"]
Result2["Option"]
subgraph Operations["Operations"]
Add["add(SIGINT)"]
Remove["remove(SIGHUP)"]
Has["has(SIGTERM)"]
Dequeue["dequeue(mask)"]
BitwiseAnd["set1 & set2"]
BitwiseOr["set1 | set2"]
BitwiseNot["!set"]
end
end
A --> Add
A --> BitwiseAnd
A --> BitwiseNot
A --> BitwiseOr
A --> Dequeue
A --> Has
A --> Remove
Add --> B
BitwiseAnd --> B
BitwiseNot --> B
BitwiseOr --> B
Dequeue --> Result2
Has --> Result
Remove --> B
Sources: src/types.rs(L126 - L166)
C API Compatibility
The SignalSet includes methods for conversion to and from the C kernel_sigset_t type, ensuring compatibility with system calls and C libraries:
to_ctype(&self, dest: &mut kernel_sigset_t): Converts the SignalSet to a C kernel_sigset_tFrom<kernel_sigset_t> for SignalSet: Converts a C kernel_sigset_t to a SignalSet
flowchart TD
subgraph subGraph1["C API"]
kernel_sigset_t["kernel_sigset_t"]
end
subgraph subGraph0["Rust Code"]
SignalSet["SignalSet (u64)"]
end
SignalSet --> kernel_sigset_t
kernel_sigset_t --> SignalSet
Sources: src/types.rs(L169 - L181)
Usage in the Signal System
Signal numbers and sets form the foundation of the signal handling system in axsignal:
- Signal identification:
Signoenumerates all possible signals that can be sent and received. - Signal masking:
SignalSetis used to represent blocked signals inThreadSignalManager. - Pending signals:
SignalSettracks which signals are pending inPendingSignals. - Signal delivery control:
SignalSetdetermines which signals can be dequeued during signal delivery.
flowchart TD
subgraph subGraph1["Signal Management"]
TSM["ThreadSignalManager"]
PSM["ProcessSignalManager"]
Pending["PendingSignals"]
Action["SignalAction"]
end
subgraph subGraph0["Signal Numbers & Sets"]
Signo["Signo"]
SignalSet["SignalSet"]
end
SendSignal["send_signal(sig)"]
TSM_Blocked["ThreadSignalManager::blocked"]
Pending_Set["PendingSignals::set"]
Dequeue["dequeue_signal(mask)"]
Dequeue --> PSM
Dequeue --> TSM
Pending_Set --> Pending
SendSignal --> PSM
SendSignal --> TSM
SignalSet --> Dequeue
SignalSet --> Pending_Set
SignalSet --> TSM_Blocked
Signo --> Action
Signo --> SendSignal
TSM_Blocked --> TSM
Sources: src/types.rs(L9 - L182)
Summary
Signal numbers and sets are fundamental components of the axsignal crate:
Signoprovides a type-safe enumeration of all signal numbers, with additional functionality to determine signal characteristics and default actions.SignalSetprovides an efficient, bit-based representation of signal collections with operations for adding, removing, checking, and dequeueing signals.- Together, they form the foundation for signal identification, blocking, and delivery throughout the signal handling system.
These components follow Unix/POSIX signal conventions while providing Rust-specific advantages like type safety and clear semantics.