Module: KairosMcp::Daemon::SignalHandler
- Defined in:
- lib/kairos_mcp/daemon/signal_handler.rb
Overview
Signal handling for the daemon (design v0.2 §3.1).
Signal → action mapping:
SIGTERM → graceful shutdown (sets @shutdown_requested)
SIGINT → graceful shutdown (same as TERM, for `Ctrl-C` during foreground runs)
SIGHUP → reload config (enqueues :reload command)
SIGUSR1 → status dump (enqueues :status_dump command)
Signal handlers run in the VM’s signal-handling context, where only a narrow subset of operations is safe. We therefore do as little work as possible inside the trap block — just flip a flag or push onto the thread-safe CommandMailbox — and let the main event loop do the work.
Constant Summary collapse
- SUPPORTED_SIGNALS =
%w[TERM INT HUP USR1].freeze
Class Method Summary collapse
-
.handle(daemon, sig) ⇒ Object
Dispatch a signal to the daemon.
-
.install(daemon) ⇒ Array<String>
Install handlers on the given daemon instance.
- .signal_supported?(sig) ⇒ Boolean
-
.uninstall ⇒ Object
Remove any handlers we installed (mainly for tests).
Class Method Details
.handle(daemon, sig) ⇒ Object
Dispatch a signal to the daemon. Kept public for tests that want to simulate signal delivery without actually raising signals.
CF-2 fix: only set atomic flags in signal context. The event loop translates flags into mailbox commands on the next tick.
62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/kairos_mcp/daemon/signal_handler.rb', line 62 def self.handle(daemon, sig) case sig when 'TERM', 'INT' daemon.request_shutdown!(sig) when 'HUP' daemon.request_reload! when 'USR1' daemon.request_status_dump! end rescue StandardError # Signal handlers must never raise — swallow everything. end |
.install(daemon) ⇒ Array<String>
Install handlers on the given daemon instance.
The daemon must respond to:
- #request_shutdown!(signal)
- #mailbox (returns a CommandMailbox)
- #logger (returns a KairosMcp::Logger or duck-equivalent)
29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/kairos_mcp/daemon/signal_handler.rb', line 29 def self.install(daemon) installed = [] SUPPORTED_SIGNALS.each do |sig| next unless signal_supported?(sig) begin Signal.trap(sig) { handle(daemon, sig) } installed << sig rescue ArgumentError, Errno::EINVAL # Platform doesn't support this signal — skip silently. end end installed end |
.signal_supported?(sig) ⇒ Boolean
75 76 77 |
# File 'lib/kairos_mcp/daemon/signal_handler.rb', line 75 def self.signal_supported?(sig) Signal.list.key?(sig) end |
.uninstall ⇒ Object
Remove any handlers we installed (mainly for tests).
45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/kairos_mcp/daemon/signal_handler.rb', line 45 def self.uninstall SUPPORTED_SIGNALS.each do |sig| next unless signal_supported?(sig) begin Signal.trap(sig, 'DEFAULT') rescue ArgumentError, Errno::EINVAL # ignore end end end |