Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When do you need to `END { close STDOUT}` in Perl?

Tags:

perl

In the tchrists broilerplate i found this explicit closing of STDOUT in the END block.

END { close STDOUT }

I know END and close, but i'm missing why it is needed.

When start searching about it, found in the perlfaq8 the following:

For example, you can use this to make sure your filter program managed to finish its output without filling up the disk:

END {
    close(STDOUT) || die "stdout close failed: $!";
}

and don't understand it anyway. :(

Can someone explain (maybe with some code-examples):

  • why and when it is needed
  • how and in what cases can my perl filter fill up the disk and so on.
  • when things getting wrong without it...
  • etc??
like image 286
jm666 Avatar asked Jun 12 '11 10:06

jm666


2 Answers

A lot of systems implement "optimistic" file operations. By this I mean that a call to for instance print which should add some data to a file can return successfully before the data is actually written to the file, or even before enough space is reserved on disk for the write to succeed.

In these cases, if you disk is nearly full, all your prints can appear successful, but when it is time to close the file, and flush it out to disk, the system realizes that there is no room left. You then get an error when closing the file.

This error means that all the output you thought you saved might actually not have been saved at all (or partially saved). If that was important, your program needs to report an error (or try to correct the situation, or ...).

All this can happen on the STDOUT filehandle if it is connected to a file, e.g. if your script is run as:

perl script.pl > output.txt

If the data you're outputting is important, and you need to know if all of it was indeed written correctly, then you can use the statement you quoted to detect a problem. For example, in your second snippet, the script explicitly calls die if close reports an error; tchrist's boilerplate runs under use autodie, which automatically invokes die if close fails.

(This will not guarantee that the data is stored persistently on disk though, other factors come into play there as well, but it's a good error indication. i.e. if that close fails, you know you have a problem.)

like image 107
Mat Avatar answered Sep 18 '22 19:09

Mat


I believe Mat is mistaken.

Both Perl and the system have buffers. close causes Perl's buffers to be flushed to the system. It does not necessarily cause the system's buffers to be written to disk as Mat claimed. That's what fsync does.

Now, this would happen anyway on exit, but calling close gives you a chance to handle any error it encountered flushing the buffers.

The other thing close does is report earlier errors in attempts by the system to flush its buffers to disk.

like image 23
ikegami Avatar answered Sep 19 '22 19:09

ikegami