Previous Page
Next Page

10.6. Cleanup

Close filehandles explicitly, and as soon as possible.

Lexical filehandles, and even localized package filehandles, automatically close as soon as their variable or localization goes out of scope. But, depending on the structure of your code, that can still be suboptimal:

    sub get_config {
        my ($config_file) = @_;

        # Access config file or signal failure...
        open my $fh, '<', $config_file
            or croak "Can't open config file: $config_file";

        # Load file contents...
        my @lines = <$fh>;

        # Storage for config data...
        my %config;
        my $curr_section = $EMPTY_STR;


        
        # Decode config data...
        CONFIG:
        for my $line (@lines) {
            # Section markers change the second-level hash destination...
            if (my ($section_name) = $line =~ m/ \A \[ ([^]]+) \] /xms) {
                $curr_section = $section_name;
                next CONFIG;
            }

            # Key/value pairs are stored in the current second-level hash...
            if (my ($key, $val) = $line =~ m/\A \s* (.*?) \s* : \s* (.*?) \s* \z/xms) {
                $config{$curr_section}{$key} = $val;
                next CONFIG;
            }

            # Ignore everything else
        }

        return \%config;
    }

The problem here is that the input file remains open after it's used, and stays open for however long the decoding of the data takes.

The sooner a filehandle is closed, the sooner the internal and external resources it controls are freed up. The sooner it's closed, the less chance there is for accidental reuse or misuse. The sooner an output filehandle is closed, the sooner the written file is in a stable state.

The previous example would be more robust if it didn't rely on the scope boundary to close the lexical filehandle when the subroutine returns. It should have been written:


    sub get_config {
        my ($config_file) = @_;

        
# Access config file or signal failure...
open my $fh, '<', $config_file or croak "Can't open '$config_file': $OS_ERROR";
# Load file contents and close file...
my @lines = <$fh>; close $fh or croak "Can't close '$config_file' after reading: $OS_ERROR";
# [Decode config data and return, as before]
}

    Previous Page
    Next Page