So, ich habe jetzt eine laufende gemischte Fork/Alarm-Lösung:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#!/usr/bin/perl
use strict;
use warnings;
use POSIX ":sys_wait_h";
pipe PREAD, CWRITE; # child -> parent
my $parent_pid = $$;
if (my $pid = fork()) {
parent($pid);
}
else {
child();
}
sub child {
close PREAD; # child - close parent end of pipe
print "child: id $$ dad $parent_pid\n";
print "child: start of proccess\n";
syswrite CWRITE, "0\n";
for (1..9) {print "child zZZZzzz\n";sleep 1;}
print "child is awaking\n";
syswrite CWRITE, "$_\n" for 1 .. 10;
print "child ending\n";
exit;
} # sub child
sub parent {
my ($pid) = @_;
close CWRITE; # parent - close child end of pipes
print "parent id $$ child $pid\n";
local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
my @erg;
eval {
alarm 15;
while (waitpid($pid, WNOHANG) == 0) {
print "parent: kind lebt noch\n";
sleep 1;
}
alarm 0;
};
if ($@) {
die "other error : $@"
unless $@ eq "alarm\n"; # propagate unexpected errors
warn "parent : child got time out!\n";
# ... Maßnahmen ergreifen um klarzumachen, dass die Verarbeitung
# unvollständig ist ...
}
else {
alarm 0; # Ist das wirklich notwendig?
chomp(@erg = <PREAD>);
print "parent got ", join(' - ', @erg), "\n";
print "parent : ", (eof(PREAD)?'ENDE':'keine Ende'), "\n";
}
kill TERM => $pid; # Kind abschießen (in beiden Fällen, einmal als Zombie,
# einmal läuft es noch und verbraucht Rechenzeit)
} # sub parent
Sinn und Zweck war, das Kind nach Überschreitung einer gewissen Zeit (hier 15 Sekunden, siehe "alarm 15") am Weiterrechnen zu hindern, andererseits aber sofort, wenn das Kind vor Ablauf dieser Zeit fertig sein sollte, weitermachen zu können.
So sieht der Ablauf in der "Shell" aus:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
C:\Daten\perl\fork>f5.pl
parent id 1500 child -1520
parent: kind lebt noch
child: id -1520 dad 1500
child: start of proccess
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
child is awaking
child ending
parent: kind lebt noch
parent got 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 - 10
parent : ENDE
Nach 9 Sekunden wacht das Kind auf, schreibt seine Daten in die Pipe und beendet sich. Der Vater nimmt die Daten entgegen und alles ist gut ;)
Und so sieht er aus, wenn man statt der 15 Sekunden nur 5 Sekunden wartet (mit "alarm 5"):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
C:\Daten\perl\fork>f5.pl
parent id 1340 child -1520
parent: kind lebt noch
child: id -1520 dad 1340
child: start of proccess
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent: kind lebt noch
child zZZZzzz
parent : child got time out!
Terminating on signal SIGTERM(15)
Nach 5 Sekunden unterbricht der ungeduldige Vater das saumselige Kind und -ähm- beendet es.
s--Pevna-;s.([a-z]).chr((ord($1)-84)%26+97).gee; s^([A-Z])^chr((ord($1)-52)%26+65)^gee;print;
use strict; use warnings; Link zu meiner Perlseite