Question

Here is the problem: I've a daemon which get requests from a client, executes a function (from some module) due to the request and returns an answer to the client. After the fork() I close STDIN,STDOUT and STDERR. One function is to check dmesg. For this I get the dmesg output through open(DMESG, "/bin/dmesg |"). I don't close this fh after reading from it, because I thought that it would close automatically after the function finished. But this doesn't happen and I get a zombie for each call of dmesg.

On How can I reinitialize Perl's STDIN/STDOUT/STDERR? I found "The problem with closing STDOUT instead of reopening is that if you open other files, they might get fd 0,1 or 2 - preventing you from reopening STDOUT in the future." by jmanning2k And I think that it has something to do with it but I don't really get it. I hope that someone can explain it to me.

I know that I can avoid the the problem e.g. by calling dmesg via qx(); or simply closing the fh but I want to understand where the zombies are coming from.

Was it helpful?

Solution

The form

open DMESG, "/bin/dmesg|";

Opens the pipe and assigns it to the dynamically scoped variable DMESG. Dynamically scoped variables actually live "forever" in Perl, being saved as necessary whenever a local is seen.

If you instead use the form

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

The lexical filehandle variable $dmesg will be closed on scope exit, assuming there's no other reason to keep it alive (i.e. it's not passed back or otherwise stored in a global variable).

OTHER TIPS

open(DMESG, "/bin/dmesg |") I don't close this fh after reading from it, because i thought that it would close automatically after the function finished.

For this to work, the handle must be lexical, so it can fall properly out of scope.

open my $dmesg, …

The problem has to do with the way Perl is implemented. Here's a piece of code from the function Perl_do_openn in file 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;
}

If you open an existing filehandle, the filehandle will be closed and reopened by open(). This doesn't happen with STD* handles, as you can see from the code above. So Perl takes the next free handle for opening and the older one remains open.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top