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)?
print() on closed filehandle $outHandleA at printingToClosedHandle.pl line 9.
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.
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).