Hallo zusammen,
da bei einem fork() unter Window nur ein Thread angelegt wird, würde ich empfehlen hier generell (sowohl unter UNIX, als auch unter Windows) den Child-Process/Fork mittels threads->exit() zu beenden.
Vorteil:
Es gibt keine Fehlermeldungen unter Windows wie:
Select error -1 (10038)
Error in PurgeComm at fhem.pl line 0.
Das Handle ist ung³ltig.
Error in GetCommTimeouts at fhem.pl line 0.
Error Closing handle 132 for \\.\com3
Das Handle ist ung³ltig.
Error closing Read Event handle 176 for \\.\com3
Das Handle ist ung³ltig.
Error closing Write Event handle 180 for \\.\com3
Das Handle ist ung³ltig.
Diese Fehlermeldungen entstehen, da bei einem normalen exit(); sämtliche offenen File-Sockets geflushed und geschlossen werden. Da aber bei einem Thread dieser immer noch mit dem Mutter-Prozess verbunden sind, läuft man dadurch in die genannten Fehler.
Die Benutzung von threads->exit() verhindert das, da hier nur der Thread beendet wird, die File Sockets aber nicht geschlossen werden. Dadurch kommt es zu keinen Beeinträchtigungen des Mutter-Prozesses und deren Sockets und der Thread beendet sich normal.
Dies funktioniert auch unter UNIX-Systemen bei einem Unix-Fork() da ja der Mutterprozess ebenfalls ein Thread ist (nämlich der Haupt-Thread) und dadurch als kompletter Prozess beendet wird.
Ich würde eh gerne die Blocking.pm auf thread-basiert umstellen. Dadurch entfällt der Rückkanal über einen Telnet Port, da das Ergebniss intern über eine Thread-Queue zurückgegeben würde.
Viele Grüße
Markus
Die perl Versionen auf den Fritzboxen sind nicht thread-faehig. Weiterhin will ich bei unserem sehr heterogenen Programmiererschaar nicht mit thread-Programmierung anfangen.
Ich hab jetzt Blocking.pm so modifiziert, dass es unter Windows threads->exit aufruft, sonst exit. Testen konnte ich es nur unter Unix.
Alles klar, werde ich heute Abend mal testen.
Vielen Dank
Gruß
Markus
Hallo Rudi,
schonmal Danke fürs einchecken. Unter Windows klappt das aber so noch nicht, da das Modul threads zum Zeitpunkt des Kills nicht geladen ist.
sub
BlockingExit($)
{
my $client = shift;
if($^O =~ m/Win/) {
close($client) if($client);
use threads;
threads->exit();
} else {
exit(0);
}
}
Am besten direkt vor das Exit ein use threads; setzen. So klappt es bei mir auch unter Windows und threads wird nur unter Windows geladen.
Viele Grüße
Markus
unter Windows gibt es im Log ebenfalls bei jedem Aufruf von BlockingCall() ein Eintrag im Log wie:
Zitat2013.02.05 18:40:15 1: Terminated -1992
2013.02.05 18:40:36 1: Terminated -192
2013.02.05 18:40:58 1: Terminated -1716
2013.02.05 18:41:19 1: Terminated -3756
2013.02.05 18:41:40 1: Terminated -2576
2013.02.05 18:42:01 1: Terminated -1552
2013.02.05 18:42:22 1: Terminated -836
2013.02.05 18:42:43 1: Terminated -2552
2013.02.05 18:43:04 1: Terminated -928
Das liegt daran, das unter Windows in Perl die Parent Process Id's als negative Zahlen dargestellt werden. Hier würde ich folgende Änderung vorschlagen.
sub
BlockingKill($)
{
my $pid = shift;
if($^O =~ m/Win/) {
Log 1, "Terminated $pid" if($pid < 0 && kill(9, $pid));
}
else
{
Log 1, "Terminated $pid" if($pid && kill(9, $pid));
}
}
Ich hoffe das ist für dich in Ordnung.
Viele Grüße
Markus
hmm klappt aber nich so wie gedacht, da die kill-Funktion unter windows immer erfolgreich zurückgibt.
Ansonsten evtl. ganz weglassen unter Windows?
Hab jetzt
eval "require threads;";
und
if($^O !~ m/Win/) {
Log 1, "Terminated $pid" if($pid && kill(9, $pid));
}
hinzugefuegt. "use" wird immer am Anfang ausgefuehrt, unabhaengig vom "if", und mit dem Windows threading Modell ist ein kill problematisch, steht jedenfalls in "perldoc perlfork" so drin.