NAME

Linux::Event::Kernel::Signal - synchronous signalfd delivery on a Loop

SYNOPSIS

use v5.36;
use Linux::Event::Loop;
use Linux::Event::Kernel::Signal;
use POSIX qw(SIGINT SIGTERM);

my $loop = Linux::Event::Loop->new;
my $signal = Linux::Event::Kernel::Signal->new(
    loop    => $loop,
    signals => [SIGINT, SIGTERM],
    on_signal => sub ($signal, $number, $count) {
        $signal->loop->stop;
    },
);
$loop->run;

DESCRIPTION

Linux::Event::Kernel::Signal converts Linux process signals into ordinary synchronous Loop callbacks. It does not execute application Perl from an asynchronous C signal handler and does not install a Perl %SIG callback for the subscribed numbers.

One object may subscribe to several signal numbers, and several Signal objects on the same Loop may subscribe to the same number. The Loop uses one shared nonblocking signalfd plus a native fan-out registry.

CALLBACKS AND SUBCLASS POLICY

Pass on_signal => sub ($signal, $number, $count) { ... } to new when a subscription should capture lexical application state. A named subclass method is useful when several subscriptions share reusable signal policy:

package Shutdown;
use parent 'Linux::Event::Kernel::Signal';

sub on_signal ($signal, $number, $count) {
    $signal->data->{listener}->close;
    $signal->loop->stop;
}

A constructor callback overrides the same-named method for one object. The effective CV is cached during construction, so signal fan-out does not perform method lookup or callback-style selection during delivery.

CONSTRUCTION

signals is required and contains the numeric signals to subscribe to. data stores arbitrary application state. loop => $loop attaches immediately; otherwise add the detached object with $loop->add($signal).

CALLBACK

A subclass may define, or new may receive:

sub on_signal ($signal, $number, $count) { ... }

$count is the number of signalfd records observed for that signal in the current complete drain. Real-time signals retain queued records; ordinary signals may already have coalesced in the kernel before signalfd observes them.

Subscribers for one signal are called in attachment order. Dispatch is safe when a callback cancels itself or another subscriber.

SIGNAL MASK OWNERSHIP

signalfd receives signals that are blocked in the consuming thread. Linux::Event records whether each subscribed signal was already blocked and restores only mask entries that Linux::Event itself changed when the last subscription is removed.

A signal number may be owned by only one Linux::Event Loop in a process. Do not also expect a Perl %SIG handler to receive a signal while that signal is blocked for signalfd consumption.

Signal masks are per-thread. Applications should establish Signal subscriptions before creating their own worker threads, or explicitly arrange equivalent blocking in those threads. Fork before attaching Signal objects; the native service is tied to its process and owning thread.

LIFECYCLE

cancel is idempotent and terminal. The Loop retains active subscriptions. Cancellation and Loop destruction remove native fan-out entries, restore owned mask state, and release application data safely, including cancellation during a callback.

SEE ALSO

Linux::Event::Loop, docs/SIGNAL-DESIGN.md.