#!/usr/bin/perl -w use Alarm::Concurrent qw( setalarm ); my $TIMELEVEL = 0; sub timeout(&;$) { my $code = shift; my $time = shift || 30; my $dietext = "Timeout " . ++$TIMELEVEL . "\n"; eval { local $SIG{__DIE__}; setalarm($time, sub { die $dietext }); $code->(); }; --$TIMELEVEL; if($@ eq $dietext) { return 0; # Timed out. } elsif($@ ne '') { die $@; # Propagate error upstream. } return 1; # Everything's ok. } timeout { timeout { sleep 10; } 3 or die "Inner timeout"; } 2 or die "Outter timeout"; print "Everything's ok.\n";