Expand description
Signal handling API for Seq
Provides Unix signal handling with a safe, flag-based approach:
- Signals are trapped and set atomic flags (no code runs in signal context)
- User code polls for signals at safe points
- Fits Seq’s explicit, predictable style
§Example
signal.SIGINT signal.trap
signal.SIGTERM signal.trap
: main-loop ( -- )
signal.SIGINT signal.received? if
"Shutting down..." io.write-line
return
then
do-work
main-loop
;§Safety
Signal handlers execute in an interrupt context with severe restrictions. This module uses only async-signal-safe operations (atomic flag setting). All Seq code execution happens outside the signal handler, when the user explicitly checks for received signals.
§Thread Safety and Concurrent Access
This module is designed to be safe for concurrent use from multiple strands:
-
Handler installation (
signal.trap,signal.default,signal.ignore): Protected by a mutex to ensure only one strand modifies handlers at a time. Concurrent calls will serialize safely. -
Flag operations (
signal.received?,signal.pending?,signal.clear): Use lock-free atomic operations with appropriate memory ordering:signal.received?: Atomic swap with Acquire ordering (read-modify-write)signal.pending?: Atomic load with Acquire ordering (read-only)signal.clear: Atomic store with Release ordering (write-only)
Multiple strands can safely check the same signal. However,
signal.received?clears the flag atomically, so if two strands both call it, only one will observetrue. Usesignal.pending?if you need non-destructive reads. -
Signal handler: Executes outside the strand context (in OS interrupt context) and only performs a single atomic store. This is async-signal-safe.
This module uses sigaction() instead of the deprecated signal() function
for well-defined behavior in multithreaded environments.
§Platform Support
- Unix: Full signal support using sigaction()
- Windows: Stub implementations (signals not supported, all operations no-op)
Functions§
- patch_
seq_ ⚠signal_ clear - Clear the flag for a signal without checking it
- patch_
seq_ ⚠signal_ default - Restore the default handler for a signal
- patch_
seq_ ⚠signal_ ignore - Ignore a signal entirely
- patch_
seq_ ⚠signal_ pending - Check if a signal is pending without clearing the flag
- patch_
seq_ ⚠signal_ received - Check if a signal was received and clear the flag
- patch_
seq_ ⚠signal_ sigalrm - Get SIGALRM constant (alarm clock)
- patch_
seq_ ⚠signal_ sigchld - Get SIGCHLD constant (child status change)
- patch_
seq_ ⚠signal_ sigcont - Get SIGCONT constant (continue)
- patch_
seq_ ⚠signal_ sighup - Get SIGHUP constant (hangup)
- patch_
seq_ ⚠signal_ sigint - Get SIGINT constant (Ctrl+C interrupt)
- patch_
seq_ ⚠signal_ sigpipe - Get SIGPIPE constant (broken pipe)
- patch_
seq_ ⚠signal_ sigterm - Get SIGTERM constant (termination request)
- patch_
seq_ ⚠signal_ sigusr1 - Get SIGUSR1 constant (user signal 1)
- patch_
seq_ ⚠signal_ sigusr2 - Get SIGUSR2 constant (user signal 2)
- patch_
seq_ ⚠signal_ trap - Trap a signal: install handler that sets flag instead of default behavior