2010-12-15 9 views
3

Hier ist das Problem: Ich habe einen Daemon, der Anfragen von einem Client erhält, führt eine Funktion (aus irgendeinem Modul) aufgrund der Anfrage und gibt eine Antwort zurück der Kunde. Nach dem fork() schließe ich STDIN, STDOUT und STDERR. Eine Funktion ist dmesg zu überprüfen. Dafür bekomme ich die dmesg-Ausgabe über offen (DMESG, "/ bin/dmesg |"). Ich schließe dieses fh nicht, nachdem ich es gelesen habe, weil ich dachte, dass es automatisch schließen würde, nachdem die Funktion beendet ist. Aber das passiert nicht und ich bekomme einen Zombie für jeden Anruf von dmesg.Perl: creating Zombies durch open() ohne close()

Auf How can I reinitialize Perl's STDIN/STDOUT/STDERR? Ich fand "Das Problem mit dem Schließen von STDOUT anstelle von Wiedereröffnung ist, dass wenn Sie andere Dateien öffnen, sie fd 0,1 oder 2 erhalten - verhindert, dass Sie STDOUT in der Zukunft wieder öffnen." von jmanning2k Und ich denke, dass es etwas damit zu tun hat, aber ich verstehe es nicht wirklich. Ich hoffe, dass mir jemand das erklären kann.

Ich weiß, dass ich das Problem vermeiden kann, z. durch Aufruf von dmesg über qx(); oder einfach die fh schließen, aber ich möchte verstehen, woher die Zombies kommen.

Antwort

6

Die Form

open DMESG, "/bin/dmesg|"; 

öffnet das Rohr und weist ihn die dynamisch variable DMESG scoped. Dynamisch begrenzte Variablen leben tatsächlich "für immer" in Perl und werden bei Bedarf gespeichert, wenn ein local angezeigt wird.

Wenn Sie stattdessen das Formular verwenden

open my $dmesg, "/bin/dmesg|"; 

Die lexikalischer Dateihandle Variable $dmesg auf Umfang Ausgang geschlossen werden, vorausgesetzt, es gibt keinen anderen Grund ist es am Leben zu halten (dh es wird nicht zurück oder auf andere Weise gespeichert gebenen eine globale Variable).

+0

Danke. das ist es und thx für die Erklärung. – olo

5

open(DMESG, "/bin/dmesg |") Ich schließe nicht diese fh, nachdem sie von ihm zu lesen, weil ich dachte, dass es automatisch nach der Funktion beendet schließen würde.

Damit dies funktioniert, muss der Handle lexikalisch sein, damit er ordnungsgemäß außerhalb des Bereichs fallen kann.

open my $dmesg, … 
+0

Ahaha das ist richtig. danke – olo

1

Das Problem hat mit der Perl-Quelle selbst zu tun. Hier ist ein Stück Code aus der Funktion Perl_do_openn in Datei doio.c:

fd = PerlIO_fileno(IoIFP(io)); 
if (IoTYPE(io) == IoTYPE_STD) { 
    /* This is a clone of one of STD* handles */ 
    result = 0; 
} 
else if (fd >= 0 && fd <= PL_maxsysfd) { 
    /* This is one of the original STD* handles */ 
    saveifp = IoIFP(io); 
    saveofp = IoOFP(io); 
    savetype = IoTYPE(io); 
    savefd = fd; 
    result = 0; 
} 

wenn Sie eine vorhandene Dateihandle öffnen, wird die Dateikennung durch offene geschlossen und wieder geöffnet werden(), Dies geschieht nicht mit STD * Griffe, wie Sie aus dem obigen Code sehen können. So nimmt Perl den nächsten freien Griff zum Öffnen und der ältere bleibt offen.