2010-12-15 125 views
3

Voici le problème: J'ai un démon qui reçoit des requêtes d'un client, exécute une fonction (à partir d'un module) en raison de la requête et renvoie une réponse à le client. Après la fourche() je ferme STDIN, STDOUT et STDERR. Une fonction consiste à vérifier dmesg. Pour cela, je reçois la sortie dmesg via open (DMESG, "/ bin/dmesg |"). Je ne ferme pas ce fh après en avoir lu, car je pensais qu'il se fermerait automatiquement après la fin de la fonction. Mais cela n'arrive pas et je reçois un zombie pour chaque appel de dmesg.Perl: créer des zombies via open() sans close()

Sur How can I reinitialize Perl's STDIN/STDOUT/STDERR? J'ai trouvé "Le problème avec la fermeture de STDOUT au lieu de la réouverture est que si vous ouvrez d'autres fichiers, ils peuvent obtenir fd 0,1 ou 2 - vous empêchant de rouvrir STDOUT dans le futur." par jmanning2k Et je pense que ça a quelque chose à voir avec ça mais je ne comprends pas vraiment. J'espère que quelqu'un peut me l'expliquer.

Je sais que je peux éviter le problème, par exemple. en appelant dmesg via qx(); ou simplement fermer le fh mais je veux comprendre d'où viennent les zombies.

Répondre

6

La forme

open DMESG, "/bin/dmesg|"; 

ouvre le tube et l'affecte à la dynamiquement scope variables DMESG. Les variables à portée dynamique vivent réellement "pour toujours" en Perl, étant enregistrées comme nécessaires chaque fois qu'un local est vu.

Si vous utilisez plutôt le formulaire

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

Le lexical filehandle variables $dmesg sera fermé à la sortie de la portée, en supposant qu'il n'y a pas d'autre raison de le garder en vie (c.-à-ce n'est pas repassé ou autrement stockées une variable globale).

+0

Merci. C'est ça et merci pour l'explication. – olo

5

open(DMESG, "/bin/dmesg |") Je ne ferme pas fh après avoir lu de lui, parce que je pensais qu'il fermerait automatiquement après la fonction terminée.

Pour que cela fonctionne, le descripteur doit être lexical, afin qu'il puisse tomber hors de portée.

open my $dmesg, … 
+0

ahaha c'est bien. merci – olo

1

Le problème concerne la source Perl elle-même. Voici un morceau de code de la fonction Perl_do_openn dans le fichier 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; 
} 

si vous ouvrez un descripteur de fichier existant, le descripteur de fichier sera fermé et rouvert ses portes en open(), Cela ne se produit pas avec STD * poignées, comme vous pouvez le voir dans le code ci-dessus. Alors perl prend la prochaine poignée libre pour l'ouverture et l'ancien reste ouvert.