[PATCH] Blocking.pm - Verwenden von threads->exit()

Begonnen von Markus Bloch, 05 Februar 2013, 00:17:36

Vorheriges Thema - Nächstes Thema

Markus Bloch

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
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

rudolfkoenig

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.

Markus Bloch

Alles klar, werde ich heute Abend mal testen.

Vielen Dank

Gruß
Markus
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Markus Bloch

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
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Markus Bloch

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
Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

Markus Bloch

hmm klappt aber nich so wie gedacht, da die kill-Funktion unter windows immer erfolgreich zurückgibt.

Ansonsten evtl. ganz weglassen unter Windows?

Developer für Module: YAMAHA_AVR, YAMAHA_BD, FB_CALLMONITOR, FB_CALLLIST, PRESENCE, Pushsafer, LGTV_IP12, version

aktives Mitglied des FHEM e.V. (Technik)

rudolfkoenig

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.