Forums Neueste Beiträge
 

open2 beendet Progamm nicht

24/02/2008 - 10:29 von Martin Laabs | Report spam
Hallo,

ich will ein kleines Progamm schreiben welches einen Stream via
STDIN übernimmt, bzip2 komprimiert und den komprimierten Stream
wieder auf STDOUT ausgibt.
Das ganze mache ich um spàter nach einer bestimmten Anzahl von
komprimierten Blöcken STDIN zu schließen und dem vorhergehendem
Progamm (dump) zu signalisieren, dass das Medium welches ich ge-
rade beschrieben habe voll ist.
So weit bin ich aber noch nicht. Erst mal soll mein Progamm identisch
zu "bzip2 -1 -" arbeiten.
Tut es auch fast. Bis zu dem Punkt wo ich alle Daten an den Filehandle
'Writer' übergeben habe. Meiner Meinung nach sollte dann, nachdem ich
close(Writer) aufgerufen habe, sich bzip2 beenden damit ich in der
Leseschleife noch den Rest via sysread auslesen kann.
Bzip2 wird aber nicht beendet und so blockert
sysread( Reader, $in, $blocksize ).

Hier mein Script: (z.B. mit dd if=/dev/random count0 |./blk.pl > out
aufrufen.)

-:<
#!/usr/local/bin/perl
use FileHandle;
use IPC::Open2;
use warnings;
#use diagnostics;

my $blocksize = 1024 * 10;
my $writecount=0;

$bzippid = open2( *Reader, *Writer, "bzip2 -1 -" );

if ( $pid = fork ) { #parrent

while ( $rlen = sysread( Reader, $in, $blocksize ) ) {
syswrite( STDOUT, $in );
}

waitpid( $pid, 0 );
print STDERR "Wrote $writecount bytes";
close(Reader) || warn "Could not close pipe (r)";
close(STDIN);
close(STDOUT);

}
else { #child

while ( $rlen = sysread( STDIN, $in, $blocksize ) ) {
$wlen = syswrite( Writer, $in );
$writecount+=$wlen;
}

close(Writer) || warn "could not close pipe (w)";
print STDERR "write-loop => pipe done";
exit;
}
:<

Hat jemand eine Idee woran es liegen könnte?

Vielen Dank,
Martin L.
 

Lesen sie die antworten

#1 mlelstv
24/02/2008 - 10:46 | Warnen spam
Martin Laabs writes:

Tut es auch fast. Bis zu dem Punkt wo ich alle Daten an den Filehandle
'Writer' übergeben habe. Meiner Meinung nach sollte dann, nachdem ich
close(Writer) aufgerufen habe, sich bzip2 beenden damit ich in der
Leseschleife noch den Rest via sysread auslesen kann.



Writer ist noch nicht von _allen_ Prozessen geschlossen, erst dann
sieht die Leseseite von Writer das EOF.

-> im Parent als erstes Writer schliessen.
-> im Child als erstes Reader schliessen.

N.B. halb abstrahierter Code ist fehleranfaellig. Wenn du schon
selbst Prozesse forkst, dann kannst du auch open2 von Hand
schreiben. Etwas mehr Aufwand, aber es wird transparent, was
genau passiert.

N.B.2. $writecount im Parent auszugeben hilft nichts, wenn du es
im Child hochzaehlst :)

Michael van Elst
Internet:
"A potential Snark may lurk in every tree."

Ähnliche fragen