ЭЛЕКТРОННАЯ БИБЛИОТЕКА КОАПП
Сборники Художественной, Технической, Справочной, Английской, Нормативной, Исторической, и др. литературы.



12.6. Automating Module Clean-Up

Problem

You need to create setup code and clean-up code for a module that gets called automatically, without user intervention.

Solution

For setup code, put executable statements outside subroutine definitions in the module file. For clean-up code, use an END subroutine in that module.

Discussion

In some languages, the programmer must call a module's initialization code before any of that module's regular functions can be safely accessed. Similarly, when the program is done, the programmer may have to call module-specific finalization code.

Not so in Perl. For per-module initialization code, executable statements outside of any subroutines in your module suffice. When the module is loaded in, that code runs right then and there. The user never has to remember to do this, because it's done automatically.

Now, why would you want automatic clean-up code? It depends on the module. You might want to write a shutdown message to a logfile, tell a database server to commit any pending state, refresh a screen, or return the tty to its original state.

Suppose you want a module to log quietly whenever a program using it starts up or finishes. Add code in an END subroutine to run after your program finishes:

$Logfile = "/tmp/mylog" unless defined $Logfile;
open(LF, ">>$Logfile")
    or die "can't append to $Logfile: $!";
select(((select(LF), $|=1))[0]);  # unbuffer LF
logmsg("startup");

sub logmsg {
    my $now = scalar gmtime;
    print LF "$0 $$ $now: @_\n"
        or die "write to $Logfile failed: $!";
}

END {
    logmsg("shutdown");
    close(LF)                     
        or die "close $Logfile failed: $!";
}

The first part of code, outside any subroutine declaration, is executed at module load time. The module user doesn't have to do anything special to make this happen. Someone might be unpleasantly surprised, however, if the file can't be accessed, since the die would make the use or require fail.

END routines work like exit handlers, such as trap 0 in the shell, atexit in C programming, or global destructors or finalizers in object-oriented languages. All the ENDs in a program are run in the opposite order that they were loaded; that is, last seen, first run. These get called whether the program finishes through normal process termination by implicitly reaching the end of your main program, through an explicit call to the exit function, or via an uncaught exception such as die or a mistake involving division by zero.

Uncaught signals are a different matter, however. Death by signal does not run your exit handlers. The following pragma takes care of them:

use sigtrap qw(die normal-signals error-signals);

END also isn't called when a process polymorphs itself via the exec function because you are still in the same process, just a different program. All normal process attributes remain, like process ID and parent PID, user and group IDs, umask, current directory, environment variables, resource limits and accumulated statistics, open file descriptors (however, see the $^F variable in perlvar (1) or Camel:2). If it didn't work this way, exit handlers would execute redundantly in programs managing fork and exec manually. This would not be good.

See Also

The standard use sigtrap pragma, also in Chapter 7 of Programming Perl; the section on "Package Constructors and Destructors" in Chapter 5 of Programming Perl and in perlmod (1); the $^F variable in the section on "Special Global Variables" in Chapter 2 of Programming Perl and in perldata (1); the fork and exec functions in Chapter 3 of Programming Perl and in perlmod (1)


Previous: 12.5. Determining the Caller's PackagePerl CookbookNext: 12.7. Keeping Your Own Module Directory
12.5. Determining the Caller's PackageBook Index12.7. Keeping Your Own Module Directory