Search code examples
perltimerinterrupt

How to create interrupt after x seconds in Perl?


Let me explain task with code example:

#!/usr/bin/perl
use strict;
use warnings;

my $t = 3;

eval {
    local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
    print "Start $t\n";
    alarm(10);
    sleep($t);  # instead of this I have some data that collect code
    alarm(0);
    print "done with $t\n";
};

if ($@) {
    die unless $@ eq "alarm\n";
    print "timeout\n";
}

Instead of sleep I have some code that push data to array. Array will be guaranteed filled by needed data during `x seconds.

Question: how to print array after x second, without using sleep (non-blocking way) ?

As far as I understand simplest way to set timer in perl is to use $SIG{ALRM}. But what to do if I don't need timer (can't use sleep), I just need to set one interrupt that must run after pre-defined amount of seconds ? Maybe I should use SIGINT for this task?

Any help appreciated.


Solution

  • To create your own interrupts, you need two threads of execution. One way to do this is to launch a child process that will signal its parent when some condition is met.

    $SIG{USR1} = \&code_to_run_after_interrupt;
    my $ppid = $$;          # process id of parent
    if (fork() == 0) {
        # child process
        sleep 15;
        kill 'USR1', $ppid;
        exit;
    }
    ... main execution thread
    

    15 seconds after the fork call, your main script will stop what it's doing, execute the code in a subroutine named code_to_run_after_interrupt, and then resume the main thread of execution.

    (I use SIGUSR1 here because handling SIGINT may make you unable to use Ctrl-C to stop your program)