# just "macro" function from our library sub Cat { local *F; open F, "< ".$_[0] or return; local $/ unless wantarray; return ; } { my $SYS_setitimer = ( join("", map { Cat("/usr/include/$_.h") } qw(syscall sys/syscall bits/syscall asm/unistd) ) =~ /^\s*#define\s*(?:__NR|SYS)_setitimer\s*(\d+)/m )[0]; my %ALARM = (); # $n = alarm_start(0.01, \$counter) or die; # $n = alarm_start(2.50, \&handler) or die; # alarm_stop($n); sub alarm_start { my ($PARENT, $time, $counter) = ($$, @_); return unless my ($n) = grep { not exists $ALARM{$_} } 50..59; @{$ALARM{$n}}{"sec","usec"} = (int($time), int(($time-int($time))*1000000)); $SIG{"NUM".$n} = ref($counter) eq "SCALAR" ? sub {$$counter++} : $counter; pipe $ALARM{$n}{READ}, $ALARM{$n}{WRITE}; if (!fork()) { $0 .= " ALARM $n"; close $ALARM{$n}{WRITE}; $SIG{ALRM} = sub { kill $n, $PARENT }; # FIXME 0 mean ITIMER_REAL from syscall $SYS_setitimer, 0, pack("llll", (@{$ALARM{$n}}{"sec","usec"})x2), "\x00"x16; read $ALARM{$n}{READ}, my $buf, 1; print "Chield $n died\n"; exit; } close $ALARM{$n}{READ}; return $n; } sub alarm_stop { $SIG{"NUM".$_[0]} = "IGNORE"; print {$ALARM{$_[0]}{WRITE}} "\n" if exists $ALARM{$_[0]}; delete $ALARM{$_[0]}; } } # Example: $n1 = alarm_start(0.001, \$c1) or die 1; $n2 = alarm_start(0.01, \$c2) or die 2; $n3 = alarm_start(0.1, \$c3) or die 3; $n4 = alarm_start(1, \$c4) or die 4; $n5 = alarm_start(1.5, \$c5) or die 5; $n6 = alarm_start(0.02, sub { $c6++ }) or die 6; $t0 = time(); $i++ while time()<$t0+10; print "Parent died: i=$i c1=$c1 c2=$c2 c3=$c3 c4=$c4 c5=$c5 c6=$c6\n";