NAME

Fugu::Signal - signal handlers for graceful shutdown

SYNOPSIS

use Fugu::Signal;

my $sig = Fugu::Signal->new;
$sig->setup_interrupt_flag('INT', 'TERM');
until ($sig->interrupted) {
    do_some_work();
}

DESCRIPTION

Fugu::Signal installs signal handlers so that a signal can interrupt a program safely. The program does not leave temporary files, child processes or half-written state behind.

setup_interrupt_flag() only sets a flag. The program must do a check of the flag and stop where a stop is safe.

The object keeps the previous handlers. restore() puts them back, and the destructor calls restore(). Thus a scoped object leaves the process in its initial state.

Each manager owns its handlers and its interrupt flag. Two managers in one process do not see each other's state. The installed handlers close over the object, so a handler always finds the manager that installed it.

new

new() creates a signal handler manager. It does not install handlers.

setup_interrupt_flag

setup_interrupt_flag(@signals) installs a handler for each named signal. The handler sets the interrupt flag and returns. No other action occurs until the program reads the flag.

restore

restore() puts back the handlers that this object replaced.

interrupted

interrupted() reports if this manager saw a handled signal.

reset_interrupted

reset_interrupted() clears the interrupt flag of this manager.

check_interrupted

check_interrupted() reports if any live manager saw a handled signal. It is a plain function, not a method. It serves code that runs far from the object, for example a poll loop deep in a library. Code that holds the object uses interrupted().

RETURN VALUES

new() returns a signal handler manager. setup_interrupt_flag(), reset_interrupted() and restore() return the object. Thus the calls can chain.

interrupted() and check_interrupted() return true if a handled signal came.

EXAMPLES

This example stops between items and not in the middle of one:

my $sig = Fugu::Signal->new;
$sig->setup_interrupt_flag('INT', 'TERM');

for my $item (@items) {
    last if $sig->interrupted;
    process($item);
}

ERRORS

No method dies.

SEE ALSO

perlipc(1), kill(2), sigaction(2), Fugu::Process

AUTHORS

Dick Olsson <hi@senzilla.io>

CAVEATS

check_interrupted() answers for the whole process. It returns true when any live manager saw a signal, and it cannot tell the caller which one.

The handlers are standard Perl signal handlers and run between opcodes, not immediately. A program that a system call blocks sees the signal when the call returns.