suaveant has asked for the wisdom of the Perl Monks concerning the following question:

I came accross some code I have to fix that someone who doesn't work here any more wrote...
open(LOGFILE, ">>$logFid") || die "Can't open log"; select((select(LOGFILE), $| = 1)[0]); # redirect stderr to the log open(STDERR, ">>&LOGFILE") || die "Can't redirect STDERR"; return(*LOGFILE{IO}, $logDate);
which is killing the newest version of FCGI do to the wierd handling of the STDERR with the FILEGLOB. All I really am interested in at the moment is what *LOGFILE{IO} does... anyone know?
                - Ant

Replies are listed 'Best First'.
(tye)Re: Wierd filehandle call
by tye (Sage) on Apr 03, 2001 at 23:39 UTC

    Symbol table entries (also called "globs") contain slots for a reference to a scalar, ref to array, ref to hash, ref to code, a bunch of IO stuff, and a few other things.

    *ARGV{ARRAY} is the same a \@ARGV. *LOGFILE{IO} gives you back an object of type IO::Handle that encapsulates the "IO stuff" of the glob.

    If this is causing you problem, you could try replacing that with \*LOGFILE.

    I don't really know much about this and have never seen it documented (which certainly doesn't mean that it isn't).

            - tye (but my friends call me "Tye")
Re (tilly) 1: Wierd filehandle call
by tilly (Archbishop) on Apr 04, 2001 at 08:19 UTC
    Let me guess, old code? Try the following (sorry, untested) version which does the same thing in a (IMHO) clearer manner.
    use IO::Handle; # time passes local *LOGFILE; open (LOGFILE, ">> $logFid") or die "Cannot write $logFid: $!"; LOGFILE->autoflush(); *STDERR = *LOGFILE; return (*LOGFILE, $logDate);

      I have to discourage *STDERR= *LOGFILE. Sure, it looks nice, but it doesn't change the underlying stderr (fd 2) so that some parts of Perl (I assume) will still use the old handle as will external programs lauched by the script (or has magic to handle this been added?).

      It also leaves you in a strange situation. How do you properly close things now? To get that correct requires way too many implementation details about Perl for my taste (it may not even be possible to do it 100% correctly -- I haven't investigate the implementation details as I don't really want to know them).

      So I agree with the rest of your code but please use open to dup to STDERR instead.

      Then there is the edge case of someone using $STDERR and $LOGFILE and getting very confused. (:

              - tye (but my friends call me "Tye")
        Good point about C code expecting the fd to still be 2.

        The edge case is not as bad a problem as you stated because I used local (not my because I was localizing a glob). However that does explain why the person only returned the IO part of the glob. (Of course I just store my filehandles in lexical variables.)

        And I don't understand why you think that properly closing the filehandle. I just do not issue a close anywhere, but instead store the glob in a lexical variable, and when the last reference to the open filehandle goes away, the close will happen. Or in old-style Perl you just use local on your typeglobs and again it works just fine.

        At least it works fine for as long as Perl keeps its reliable destruction semantics around...