On 2011-06-16 19:16, C.DeRykus wrote:
Ruud:
C.DeRykus:

Another solution, not necessarily more elegant, but
more familiar to most  is an eval {} and alarm pair:

EVAL: {
      eval {
           local $SIG{ ALRM } = sub { die "alarm"; };
           local $SIG{ USR1 } = sub { die "usr1" };
           alarm $sleeptime;
           ... some long running operation here ....
           alarm 0;
           1;
       } or do {

Insert:
               my $eval_error = $@ || "Zombie error!";

Huh?   If you insert that statement before doing 'alarm 0',
then, there's a potential have a race condition with the
alarm going off and terminating the entire program with
"alarm clock" before you can even check $@.

Realize that the alarm is then already reset (to the earlier setting) because the localization gets out of scope.


        eval {  ...  ; "foo" happens and sets $@='bar';
                  ...
               };
               my $eval_error = $@ || "Zombie error!";
                      #  alarm actually does go off now
                      #  and terminates program
               alarm 0;      #  too late
               ....
Therefore you wouldn't want to insert any statement
before turning off the alarm.

Because the alarm signal is localized (to the eval{}), it is not active in the do{}.

To support 'nested' alarms (actually more 'in turns' than 'nested'), you might want to do it like this:

EVAL: {
  my $prev_timeout = alarm 0;  # stop any outer alarm
  my $timeout = 20;

  eval {
      my $alarm_on = 1;
      local $SIG{ ALRM } = sub { die "evalarm" if $alarm_on };
      local $SIG{ USR1 } = sub { $alarm_on = 0; die "usr1" };
      alarm $timeout;

      ... some long running operation here (that might die itself) ...

      $alarm_on = 0;
      alarm $prev_timeout;  # re-activate any outer alarm
      1;  # success
  }
  or do {
      my $eval_error = $@ || "Zombie error!";
      alarm $prev_timeout;  # re-activate any outer alarm

      if    ( $eval_error =~ /evalarm/ ) { warn "expired..." }
      elsif ( $eval_error =~ /usr1/    ) { redo EVAL }
      else                               { die $eval_error }

  };
}

--
Ruud

--
To unsubscribe, e-mail: beginners-unsubscr...@perl.org
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/


Reply via email to