Schrift
[thread]7679[/thread]

sysread() und Sun-Solaris: Scheinen sich zu hassen



<< >> 6 Einträge, 1 Seite
dcraul
 2006-02-07 12:49
#62640 #62640
User since
2006-01-27
11 Artikel
BenutzerIn
[default_avatar]
Hallo,

ich habe eine Routine, die mittels sysread() 2K grosse Blöcke liest. Das klappt unter Windows auch ganz prima. Lasse ich das Perl-Skript aber unter Sun-Solaris laufen (gleiche Perl-Version 5.8.4), dann "hängt" der sysread, wenn weniger Bytes tatsächlich vorhanden sind, als im Puffer angegeben wurde.
Es werden also nicht die gelesenen Bytes zurückgegeben, sondern das Programm steht.
Weiss jemand abhilfe? Muss man den Input irgendwie terminieren, damit der sysread nicht hängt?
murphy
 2006-02-07 14:20
#62641 #62641
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Eigentlich sollte das nicht passieren, was man aber mal probieren könnte, wäre den Dateideskriptor mittels
Code: (dl )
1
2
3
use Fcntl qw(F_GETFL F_SETFL O_NONBLOCK);

fcntl(FILE, F_SETFL, O_NONBLOCK | (fcntl(FILE, F_GETFL, 0) or die "can't get flags: $!")) or die "can't set flags: $!"
in den nichtblockierenden Modus zu schalten.
When C++ is your hammer, every problem looks like your thumb.
dcraul
 2006-02-07 15:21
#62642 #62642
User since
2006-01-27
11 Artikel
BenutzerIn
[default_avatar]
fcntl hat zwar ein wenig geholfen aber dann kamen gar keine Daten mehr????

Ich habe mir aber mittlerweile wie folgt geholfen, sicherlich nicht sonderlich elegant, funktioniert aber sogar mit Netzwerk-Sockets über die ich eigentlich an das Problem gekommen bin.

anstatt:
my $n = sysread($self, $_[0], 2048, length($_[0]));


folgendes:
my ($x,$n);
my $lent=1;

while($lent<=2048)
{
eval {
local $SIG{ALRM} = sub{die "alarm\n"};
alarm(1);
$n = sysread($self,$x,1);
alarm(0);
$_[0] = "$_[0]"."$x";
$lent++;
};
if($@)
{
last;
}
}
$n=$lent;
murphy
 2006-02-07 16:07
#62643 #62643
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Wenn du aus Netzwerksockets liest und nicht aus Dateien, dann musst du unter *nix definitiv in den nichtblockierenden Modus schalten, sofern dein Programm nicht ewig auf Daten warten soll. Unter Windows sind Sockets soweit ich weiß standardmäßig nichtblockierend.

Ich kann Dir so aus der hohlen Hand heraus natürlich nicht sagen, warum dein Programm unter Solaris nicht wie gewünscht funktioniert.

Ein wichtiger Hinweis für nichtblockierende Ein- oder Ausgabe ist noch, dass man den Fehlerstatus von sysread überprüfen sollte: Gibt sysread undef zurück und steht $! auf EWOULDBLOCK, so heißt das, dass keine Daten gelesen wurden, weil die Leseoperation blockiert hätte. Gibt sysread 0 zurück, so heißt das, dass keine Daten gelesen wurden, weil definitiv keine mehr da sind (Datei zu Ende oder Socketverbindung geschlossen).
When C++ is your hammer, every problem looks like your thumb.
dcraul
 2006-02-07 16:29
#62644 #62644
User since
2006-01-27
11 Artikel
BenutzerIn
[default_avatar]
Inzwischen tut es ja und Performance-kritisch ist das Programm auch nicht ... von daher bin ich erst mal zufrieden.
Das mit dem non-Blocking IO war schon ein guter Tipp, so habe ich meine Lösung gefunden.

Das mit den Sockets werde ich garantiert im Kopf behalten, nach n Tagen herumprobieren ;-)
murphy
 2006-02-07 16:52
#62645 #62645
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Ich habe gerade mal auf einer Solaris 9 Kiste mit Perl 5.6.1 herumgetestet und Deine Problem mit nichtblockierender Ein- und Ausgabe und sysread nicht reproduzieren können. Für Tests direkt auf C-Ebene war ich zu faul, aber ich glaube trotzdem nicht, dass es sich hier um ein Problem mit dem Betriebssystem handelt.

Naja, wenn Dir bereits weitergeholfen ist, legen wir dieses merkwürdige Problem am besten zur Seite ;)
When C++ is your hammer, every problem looks like your thumb.
<< >> 6 Einträge, 1 Seite



View all threads created 2006-02-07 12:49.