Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How severe is it if we do not close a file in Perl?

How severe is it if we do not close a file in Perl? Will it affect the program or file if I access it again in the same program?

like image 746
Daanish Avatar asked Oct 03 '12 06:10

Daanish


1 Answers

Global filehandles will stay around until your program exits. This may be bad, but as you probably shouldn't be using global filehandles anyway, this is a non-issue.

Lexical filehandles with my are closed when their scope is left / their reference count drops to zero.

If the name of a filehandle is re-used, the previous filehandle is closed implicitely. The following script reuses the same filehandle to print the first five lines of any number of files:

my $fh;
foreach my $filename (@ARGV) {
  open $fh, "<", $filename or die "Can't open $filename";  # $fh is re-used
  print scalar <$fh> // next for 1 .. 5;                   # // is the defined-or
}

When working with files, explicitely closing the FH is unimportant. However, it is critical when doing IPC. Closing a writing end to a pipe indicates EOF to the reading end.

When forking, all unused filehandles should be closed, because they are duplicated while forking. This means that closing a pipe in one process might not be sending the desired EOF, because the same pipe is still open in a related process.

Here is a program that demonstrates the importance of close in IPC:

pipe my $out, my $in or die $!;

if (fork()) {  # PARENT
  close $out;                            # close unused handle    (important!)
  select $in;
  $| = 1;                                # set $in to autoflushed (important!)
  $SIG{PIPE} = sub {die "Parent"};       # die, when the pipe is closed
  print ++$i, "\n" and sleep 1 while 1;  # print one number per second
} else {       # CHILD
  close $in;                             # close unused handle
  print scalar <$out> for 1 .. 5;        # read numbers 1 to 5 from the pipe
  close $out;                            # close the pipe (and trigger SIGPIPE)
  sleep 5;                               # wait, then exit
  die "Child";
}

The output of this program is the numbers 1 to 5. Then the child closes its end to the pipe, triggering SIGPIPE in the parent. While the parent dies, the child lingers around for 5 seconds until it dies too.

This works because the parent closed its reading end to the pipe. If close $out is removed from the parent, SIGPIPE would not be triggerd, and the program print numbers ad infinitum.

like image 138
amon Avatar answered Sep 21 '22 11:09

amon