Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

No error or warning for trying to print to an already closed filehandle

In the following small code, I do not get an error or a warning for lines [09] and [18]. The only warning I get is with line [21]:

use strict;                                              # [01]
use warnings FATAL => 'unopened';                        # [02]
                                                         # [03]
open(my $outHandleA, ">outputA.txt") or die ("A: $!\n"); # [04] Opened $outHandleA
print $outHandleA "FILE A\n";                            # [05]
close $outHandleA;                                       # [06] Closed $outHandleA
                                                         # [07]
print $outHandleA;                                       # [08]
print $outHandleA "ABC\n";                               # [09] <---
print $outHandleA;                                       # [10]
print "-----";                                           # [11]
                                                         # [12]
open(OUT, ">outputB.txt") or die ("B: $!\n");            # [13] Opened OUT
print OUT "FILE B\n";                                    # [14]
close OUT;                                               # [15] Closed OUT
                                                         # [16]
print OUT;                                               # [17]
print OUT "DEF\n";                                       # [18] <---
print OUT;                                               # [19]
                                                         # [20]
print DOES_NOT_EXIST_HANDLE "GHI\n";                     # [21] Raises a FATAL warning
                                                         # [22]
print "JKL";                                             # [23] Does not reach here (as expected)

However, shouldn't lines [09] and [18] also raise an error or a warning like the following since it is closed (unopened)?

  • ERROR: print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
  • WARNING: print() on unopened filehandle $outHandleA at printingToClosedHandle.pl line 9.

This might be an issue with my version of Perl which is "perl 5, version 28, subversion 1 (v5.28.1) built for MSWin32-x64-multi-thread". Furthermore, here is the output of the program I get below:

outputA.txt outputB.txt STDOUT
FILE A FILE B GLOB(0xfeb428)GLOB(0xfeb428)-----

The STDOUT output in above table is from lines [08], [10], and [11]. Please note that the value between the parenthesis (...) in the above table might change with each execution.

like image 603
mak Avatar asked Feb 26 '21 04:02

mak


1 Answers

There is a difference between a filehandle that has been opened (initialized) and got closed, and one that has not been opened at all; attempting to print to them draws different warnings. One of 'unopened' entries in perldiag says

%s() on unopened %s
(W unopened) An I/O operation was attempted on a filehandle that was never initialized. You need to do an open(), a sysopen(), or a socket() call, or call a constructor from the FileHandle package.

while an entry for print() on closed filehandle says

print() on closed filehandle %s
(W closed) The filehandle you're printing on got itself closed sometime before now. Check your control flow.

They both get the warnings though.

When use warnings FATAL => 'unopened' alone is enabled then printing to a filehandle that had been initialized but then closed does not get a warning.

use warnings;
#use warnings FATAL => 'unopened';
use strict;
use feature 'say';

open my $stdout, '>&', *STDOUT;    # a copy

say $stdout "hi";
close $stdout;
say $stdout "to lexical, closed";  # it warns (l.10)

FATAL_warnings_unopened: { 
    no warnings;                   # change to FATAL for 'unopened'
    use warnings FATAL => 'unopened';

    say $stdout "with FATAL to closed fh";      # no warning
    close STDOUT;
    say "with FATAL to STDOUT";                 # no warning

    say NON_EXISTENT_FH "no such filehandle!";  # l.20
};

say STDERR 'done';

This prints

hi
say() on closed filehandle $stdout at warnings_FATAL.pl line 10.
say() on unopened filehandle NON_EXISTENT_FH at warnings_FATAL.pl line 20.

It does exit, per FATAL and an unopened filehandle NON_EXISTENT_FH inside the block, but there is no warnings for the print to $stdout right above it. There is a warning for the first such print. A print to STDOUT which just got closed doesn't get a warning either.

If we uncomment the use warnings FATAL... line in the very beginning (and remove other warnings lines) then no warnings are issued for printing to closed handles, at all.

A very close reading of the docs for the warnings pragma is helpful. In short, I'd suggest to always first have use warnings; on its own, and then add a statement for categories wanted to be made FATAL (where multiple categories may be added in the same statement).

like image 174
zdim Avatar answered Sep 29 '22 16:09

zdim