sub cheatemall { my $givetime = shift; my $curtime = time(); my $oldalarm; my $oldsig = $SIG{ALRM}; $SIG{ALRM} = die ( 'ALARM' ); eval { $oldalarm = alarm( $givetime ); alarm( $oldalarm ) if ( $oldalarm < $givetime ); if ( ... ) { ## Apply your logic here. &reset_old_alarm( $curtime, $oldalarm ); return ...; ## return X } else { &reset_old_alarm( $curtime, $oldalarm ); return ...; ## return Y } }; ## We must have died out to get here. if ( $@ =~ /OLD ALARM/ ) { ## We got caught on a parent alarm. Re-create that ## alarm outside of our local eval block. kill( 'ALRM', $$); } elsif ( $@ =~ /ALARM/ ) { ## We alarmed out locally. return ...; ## return Y } else { ## Died for some other reason.. handle it here. } } sub reset_old_alarm { ## If you want to do object oriented stuff, you could ## make this be sub DESTROY so that this logic happens ## whenever your watchdog object goes out of scope. my ($curtime, $oldalarm) = @_; return alarm(0) if ( $oldalarm == 0); $oldalarm -= ( time() - $curtime ); die ( 'OLD ALARM' ) if ( $oldalarm <= 0 ); alarm($oldalarm); }