hatz has asked for the wisdom of the Perl Monks concerning the following question:

Hi perlmonks!

I was coming back to perl coding recently, and I have doubts about a couple of things concerning "exiting my program with die or exit while another file is opened".

I finished writing a ~1k lines script which is "reading files, checking stuffs, reporting errors with print() and exiting in case of blocking error" and I figured I had to add a log file to make it easier to use.

My 2 questions are :

1/ What is the best way to deal with it? I already thought about it and cam with several ideas:

- write a subroutine print_log() to replace my print() information text. The drawback of it is that the log file is opened and closed a lot of time and I'm afraid about performances

- use a global filehandle and close the file at the very end of the program. The drawback here is that I've always heard "close what you open", so I'm not sure what would happen if my program exits before my close() command because of other reasons such as another file that cannot be opened (the famous "open $bar or die")

2/ Is it really a problem to have one file left opened before exiting the program? (is it dangerous?)

I probably miss easier solutions to deal with log file writing, and I am eager to learn any good habit to make my code better.

Thank you

  • Comment on die command while other files are opened

Replies are listed 'Best First'.
Re: die command while other files are opened
by Apero (Scribe) on Dec 05, 2015 at 04:29 UTC

    The information provided earlier by Athanasius is quite valid and I won't repeat it here. However, I'll also add that under normal conditions, file-handles will auto-close when they fall out of scope (demo code for this is below.) However, it's unwise to rely on this as you cannot test that the closing finished properly.

    Because buffers may not always be flushed through the perlio layer, you don't actually know that the content you sent to the handle really got written to disk. You might call the IO/Handle method $fh->flush() to try and force buffers to be flushed early, or simply verify you set autoflush on the file handle to flush buffers as soon as practical.

    The code below explicitly sets autoflush (using the $| variable) to 0, or false. In recent-ish versions of IO::Handle, autoflush tends to be turned on by default.

    How to use this example: you should open 2 terminals in the path that you save this program. Then start the program, and once it is started, run the command tail -f out.log to watch the realtime progress of the output file in another terminal. What you will find is that with autoflush off, nothing is written until the filehandle falls out of scope. Note that we never closed it, but this also means we have no way of knowing if the data really got written out to disk (and thus we couldn't print an error message to STDERR about such a problem.

    Bonus points: turn autoflush on in this code, and see what changes. Figure out why.

    Here's the sample code:

Re: die command while other files are opened
by Athanasius (Archbishop) on Dec 05, 2015 at 02:59 UTC

    Hello hatz,

    I'm not sure what would happen if my program exits before my close() command because of other reasons such as another file that cannot be opened (the famous "open $bar or die")

    Put the close command in an END { ... } block. Code in END blocks runs when the program terminates, even if the termination is caused by an uncaught exception or an exit command:

    12:55 >perl -wE "END { say 'Bye!' } say 'Hi!'; die 'D\'oh!';" Hi! D'oh! at -e line 1. Bye! 12:55 >perl -wE "END { say 'Bye!' } say 'Hi!'; exit 0;" Hi! Bye! 12:55 >

    See perlmod#BEGIN, UNITCHECK, CHECK, INIT and END.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thank you for your answer.

      I am going to use this END function.

      END { close(LOG) if (tell(LOG) != -1);} This looks perfect!
Re: die command while other files are opened
by hippo (Archbishop) on Dec 05, 2015 at 10:21 UTC
    I probably miss easier solutions to deal with log file writing, and I am eager to learn any good habit to make my code better.

    Your specific questions have been addressed by other brothers so I'll just point out that there is a wealth of already-written code to solve common problems on CPAN, which is one of Perl's great strengths. Have a browse through the Log tree and see if some of the modules there would suit your requirements.