Thread Logikaufbau bei Parallel::ForkManager (36 answers)
Opened by bianca at 2013-09-27 10:20

bianca
 2013-09-27 20:38
#170725 #170725
User since
2009-09-13
6977 Artikel
BenutzerIn

user image
Habe so getestet:
Code (perl): (dl )
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
#!/usr/bin/perl
use strict;
use warnings;
use diagnostics;
use Parallel::ForkManager 1.05;

if (open(my $fh,'<','config.pl')) {
    my $config = eval do { 
        local $/;
        <$fh>;
    };
    die "Fehler, kann Konfigurationsdatei nicht verarbeiten '$@'\n" if $@;
    close($fh) or die "Fehler, kann Konfigurationsdatei nicht schliessen '$!'\n";
    my $forkmanager = Parallel::ForkManager->new($config->{max_prozesse});
    $forkmanager->run_on_start(
        sub {
            my ($pid,$file) = @_;
            print "Sohn '$pid' startet mit Datei '$file'\n";
        },
    );
    $forkmanager->run_on_finish(
        sub {
            my ($pid) = @_;
            print "Sohn '$pid' ist beendet\n";
        },
    );
    $forkmanager->run_on_wait(
        sub {
            print "Warte auf Auftraege\n"
        },
        $config->{poll_interval},
    );
    my $lauf = 1;
    while ($lauf) {
        if (opendir my $vh,$config->{data_pfad}) {
            foreach my $file (
                grep {
                    $_ =~ /^[a-z0-9]+\-auftrag.dat$/
                        &&
                    !-z $_
                }
                readdir $vh
            ) {
                print "Datei $file gefunden\n";
                rename("$config->{data_pfad}/$file","$config->{data_pfad}/$file-erl");
                my $pid = $forkmanager->start($file) and next;
                if (!$pid) {
                    # Sohn
                    print "Hier meldet sich ein Sohn von der Front\n";
                    $forkmanager->finish();
                }
                else {
                    die "Fehler, kann Sohnprozess nicht starten\n";
                }
            }
        }
        $lauf = 0 if -f "$config->{data_pfad}/stop.dat";
    }
    $forkmanager->wait_all_children;
}
else {
    die "Fehler, kann Konfigurationsdatei nicht oeffnen '$!'\n";
}

Die config.pl:
Code (perl): (dl )
1
2
3
4
5
6
7
8
#
# Config
#
{
  'max_prozesse'    => 5,       # max. Prozesse gleichzeitig
  'poll_interval'   => 1,       # Wartezeit zwischen Läufen
  'data_pfad'       => '.',     # Pfad für die Auftragsdateien
}

Erst kommt diese Anzeige:
Code: (dl )
1
2
3
Datei 1-auftrag.dat gefunden
Sohn '-5820' startet mit Datei '1-auftrag.dat'
Hier meldet sich ein Sohn von der Front

Dann lege ich die Datei stop.dat an und es kommt zusätzlich diese Ausgabe:
Code: (dl )
1
2
Warte auf Auftraege
Sohn '-3072' ist beendet


Frage 1: Ich hätte erwartet, dass die Ausgabe "Warte auf Auftraege" eigentlich jede Sekunde kommt, denn $config->{poll_interval} steht auf 1 und die Methode run_on_wait() verstehe ich als Anweisung für das Warten auf Kinder. Wo liegt mein Denkfehler?
Quote
If $period is defined, then $code is called periodically and the module waits for $period seconds between the two calls.


Frage 2: Warum kommt die Ausgabe "Sohn '-3072' ist beendet" erst nach Ende des gesamten Programms? Der Sohn macht doch außer einem print nichts und müsste doch sofort nach seinem Start terminieren. Wo liegt hier der Fehler?
Quote
You can define a subroutine which is called when a child is terminated. It is called in the parent process.


Frage 3: Aus der Doku verstehe ich diesen Satz nicht:
Quote
The "and next" skips the internal loop in the parent process.

Mein Script verhält sich nicht anders, wenn ich "and next" weg lasse. Warum?
10 print "Hallo"
20 goto 10

View full thread Logikaufbau bei Parallel::ForkManager