Skip Menu |
 

This queue is for tickets about the Sys-AlarmCall CPAN distribution.

Report information
The Basics
Id: 54122
Status: open
Priority: 0/
Queue: Sys-AlarmCall

People
Owner: Nobody in particular
Requestors: UNERA [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Download (untitled) / with headers
text/plain 1.7k
Hi, there! I tried to use Your module, but I was met by the problem: If the function which was given to alarm_call as second parameter uses eval-die blocks and is broken when it does eval block, then alarm_call works incorrectly. Test in atatche showes this problem. You can see the problem if You try print stack in function which uses as $SIG{ALRM} handler. stack will point to broken place. If this place is eval, die from this function will be catched by its eval. I began to try the problem (limit any function by time) and found the solve: we must use "bad" goto statement. Structure of alarm_call must be such this function: sub dtimeout { my ($timeout, $code, @args) = @_; my $prev_alarm = alarm 0; my $start_time = time; my $wantarray = wantarray; # флаг о том что кончилось время на работу my $alarmed; my @res; eval { local $SIG{ALRM} = sub { $alarmed = 1; goto FOO_DONE; }; alarm $timeout; if ($wantarray) { @res = eval { $code->(@args) }; } elsif (defined $wantarray) { $res[0] = eval { $code->(@args) }; } else { eval { $code->(@args) }; } alarm 0; die if $@; }; FOO_DONE: my $e = $@; $e = 'Timeout::alarm' if $alarmed; my $passed_time = time - $start_time; if ($prev_alarm) { if ($passed_time >= $prev_alarm) { kill ALRM => $$; } else { alarm $prev_alarm - $passed_time; } } die $e if $e; return unless defined $wantarray; return @res if $wantarray; return $res[0]; } "bad" goto cleans stack and we can really break the function. above function was got from my code :)
Subject: test.pl
Download test.pl
text/x-perl 892b
#!/usr/bin/perl use warnings; use strict; use utf8; use open qw(:std :utf8); use Test::More tests => 2; use 5.10.0; BEGIN { use_ok 'Time::HiRes'; use_ok "Sys::AlarmCall"; } sub test_timeout_eval { my @res1 = alarm_call(1, sub { sleep 1.5; sleep 1.5; @_ }, 1, 2, 3); unless ($res1[0] ~~ 'TIMEOUT') { diag "alarm_call didn't break test function"; return 0; } my $time = Time::HiRes::gettimeofday; my @res2 = alarm_call(1, sub { eval { sleep 1.5; }; sleep 1.5; @_ }, 1, 2, 3); $time = Time::HiRes::gettimeofday - $time; unless($res2[0] ~~ 'TIMEOUT') { diag "alarm_call didn't break function with eval, and returned:\n\t" . join("\n\t", @res2) . "\nfunction worked: $time seconds\n"; return 0; } return 1; } ok(test_timeout_eval, "Testing breaking function which uses eval");
Download (untitled) / with headers
text/plain 175b
Show quoted text
> I began to try the problem (limit any function by time) and found the > solve: we must use "bad" goto statement.
Hgm. "bad goto" doesn't solve this problem, too any ideas?


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.