Search code examples
perlfilehandle

Why I am getting "print() on closed filehandle with bad file descriptor" in my Perl script?


I have a TCP server in Perl (revision 5.0 version 8 subversion 0) which use this subroutine to log in a file.

sub logger {
  return if ($LOGFILE eq "") ;
  my ($idt, $str) = @_ ;
  unless( defined($str) ) {
    $str = $idt ;
    $idt = '' ;
  }
  my ($s,$m,$h,$J,$M,$A) = localtime(time()) ;
  if(!open(OUT,">>$LOGFILE")) {
    warn "logger:error open [$LOGFILE]:[$!]\n";
    return;
  }
  if (!printf OUT "%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s %s -> %s\n",
          $A+1900, $M+1, $J, $h, $m, $s, $idt, $HOSTNAME, $str) {
    warn "logger:error print [$LOGFILE]:[$!]\n";
    return;
  }
  if (!close(OUT)) {
    warn "logger:error close [$LOGFILE]:[$!]\n";
    return;
  }
}

So there is simultaneous writing in this log file. Exceptionally , I have this error in STDERR:

printf() on closed filehandle

logger :error print [/my/path/logFile.LOG]:[Bad File Descriptor]

without any error on open!

How can I resolve this problem?


Solution

  • OUT is a package global. Assuming upgrading to a real logging system such as Log4perl is out of the question, you can use a lexical file handle called $OUT:

    sub logger {
        $LOGFILE or return;
        my ($idt, $str) = @_ ;
    
        unless( defined($str) ) {
            $str = $idt ;
            $idt = '' ;
        }
    
        my ($s,$m,$h,$J,$M,$A) = localtime(time()) ;
    
        my $OUT;
    
        unless (open $OUT, '>>', $LOGFILE) {
            warn "logger:error open [$LOGFILE]:[$!]\n";
            return;
        }
    
        unless (printf $OUT 
            "%4.4d/%2.2d/%2.2d %2.2d:%2.2d:%2.2d %s %s -> %s\n",
            $A+1900, $M+1, $J, $h, $m, $s, $idt, $HOSTNAME, $str
        ) {
            warn "logger:error print [$LOGFILE]:[$!]\n";
            return;
        }
    
        unless (close $OUT) {
            warn "logger:error close [$LOGFILE]:[$!]\n";
            return;
        }
    
        return 1;
    }