Search code examples
perltimetimeoutolesubroutine

Perl subroutine timeout


I have a subroutine that normally takes 1 second to run. Sometimes, it can run infinitely. I want to move on in the code if the subroutine is taking too long (> 10 seconds) and ignore that run of that subroutine. Here is what I have so far using alarm.

use Win32::OLE;

eval { 
    local $SIG{ALRM} = sub { die "alarm\n" };
    alarm 10;                   # schedule alarm in 10 seconds 
    &do_the_subroutine;
    alarm 0;                    # cancel the alarm
};

if ($@) {
    $error_string .= $script;
    #Do something else if the subroutine took too long.
}

do_the_subroutine{
# use existing instance if Excel is already running
    eval {$ex = Win32::OLE->GetActiveObject('Excel.Application')};
    die "Excel not installed" if $@;
    unless (defined $ex) {
        $ex = Win32::OLE->new('Excel.Application', sub {$_[0]->Quit;})
                or die "Oops, cannot start Excel";
    }

    # get a new workbook
    $book = $ex->Workbooks->Add;

    # write to a particular cell
    $sheet = $book->Worksheets(1);
    $sheet->Cells(1,1)->{Value} = "foo";

    # write a 2 rows by 3 columns range
    $sheet->Range("A8:C9")->{Value} = [[ undef, 'Xyzzy', 'Plugh' ],
                                       [ 42,    'Perl',  3.1415  ]];

    # print "XyzzyPerl"
    $array = $sheet->Range("A8:C9")->{Value};
    for (@$array) {
        for (@$_) {
            print defined($_) ? "$_|" : "<undef>|";
        }
        print "\n";
    }

    # save and exit
    $book->SaveAs( 'test.xls' );
    undef $book;
    undef $ex;
}

&do_the_subroutine never returns so I'm not able to move on. I'm also not able to put this block of code inside that subroutine. Any thoughts?


Solution

  • I suspect that what you want to do is simply not natively possible with alarm on Windows.

    From perldoc perlport:

    alarm Emulated using timers that must be explicitly polled whenever Perl wants to dispatch "safe signals" and therefore cannot interrupt blocking system calls. (Win32)