Perl subroutine timeout
Asked Answered
M

1

6

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?

Merriment answered 28/7, 2015 at 15:38 Comment(15)
Could you share the subroutine's code? It works fine for me, see this demo: ideone.com/KycD4SIndent
I can't seem to recreate this behavior, using the same code I see the alarm going off. Is there more code that we are not seeing here? Can you show the definition of do_the_subroutine?Pylorectomy
Hello, I have added the definition.Merriment
The OLE stuff looks like it could be slow.Heiser
@Heiser yes.. hence why I am doing this.Merriment
I wonder if the alarm signal thing is handled differently with Windows signals.Aqua
What is your question? Would this be a better fit for codereview.stackexchange.com?Academy
@Academy the question is: How to make it quit the subroutine after 10 seconds.Merriment
I was thinking along those lines @sobrique. But also maybe that it runs something external and for that the handler isn't invoked. So I tried to use sub do_the_sub { system 'sleep 15' } on my Linux box. Works just the same. No problems visible. We need a Windows box.Heiser
<sarcasm>Maybe if you change that comment from schedule alarm in 15 seconds to 10 seconds... </sarcam> :)Heiser
@Academy This question would be off-topic for CR. This is about hunting down a known bug and altering functionality of code. Please read A Guide to Code Review for Stack Overflow usersBrennabrennan
@SimonAndréForsberg, yes, thanks. I'd misunderstood the OP's "&dosub never returns" remark to simply be a restatement of his "sometimes it can run infinitely."Academy
FWIW perlmonks.org/?node_id=505473 also seems to indicate OLE doesn't play well with alarm. perhaps move the work to a child process or a thread?Cougar
of course, the other question might be - why does that sub 'stall' - it doesn't look like it should infinite loop or anything.Aqua
as to why it stalls, on my Windows box I got a pop-up from Microsoft Excel asking "A file named 'test.xls' already exists in this location. Do you want to replace it?". I assume the hang is based on that.Greatly
G
4

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)

Greatly answered 28/7, 2015 at 16:32 Comment(1)
Thought it might be something like that. Well done for doing the digging :)Aqua

© 2022 - 2024 — McMap. All rights reserved.