Path: news.ruhr-uni-bochum.de!news.uni-stuttgart.de!uniol!uni-erlangen.de!news.tu-chemnitz.de!irz401!fu-berlin.de!main.Germany.EU.net!EU.net!www.nntp.primenet.com!nntp.primenet.com!ddsw1!news.mcs.net!van-bc!unixg.ubc.ca!nntp.cs.ubc.ca!psgrain!nntp.teleport.com!usenet
From: [email protected]
Newsgroups: comp.lang.perl.announce,comp.lang.perl.misc
Subject: ANNOUNCE: AtExit-1.02 now on CPAN
Followup-To: comp.lang.perl.misc
Date: 6 Sep 1996 20:54:15 GMT
Organization: Motorola AIEG Northbrook
Lines: 166
Approved: [email protected] (comp.lang.perl.announce)
Message-ID: <[email protected]>
Reply-To: [email protected]
NNTP-Posting-Host: kelly.teleport.com
Keywords: Perl5, atexit()
X-Disclaimer: The "Approved" header verifies header information for article transmission and does not imply approval of content.
Xref: news.ruhr-uni-bochum.de comp.lang.perl.announce:419 comp.lang.perl.misc:44494

Version 1.02 of my AtExit package is now available on CPAN as

   $CPAN/authors/id/BRADAPP/AtExit-1.02.tar.gz

where $CPAN is the leading path to your nearest CPAN site.

AtExit.pm is a very simple Perl5 module which provides a function named
atexit() to perform standard C-style exit processing, and another
function named rmexit() to remove functions registered with atexit().
The manpage for AtExit is included below my signature.

If youre having trouble connecting to CPAN, let me know. The package is
pretty small (about 430 lines of text, just over 16Kbytes).  It shouldnt
be much problem to email it.

AtExit is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

------------------------------------------------------------------------------
[email protected]   Motorola AIEG, Northbrook, IL USA
"And miles to go before I sleep."     DISCLAIMER: I said it, not my employer!
------------------------------------------------------------------------------

NAME
   atexit -- Register a subroutine to be invoked at program-exit time.
   rmexit -- Unregister a subroutine that was registered with atexit.

SYNOPSIS
   use AtExit;

   sub cleanup {
       my @args = @_;
       print "cleanup() executing: args = @args\n";
   }

   $_ = atexit(\&cleanup, "This call was registered first");
   print "first call to atexit() returned $_\n";

   $_ = atexit("cleanup", "This call was registered second");
   print "second call to atexit() returned $_\n";

   $_ = atexit("cleanup", "This call should've been unregistered by rmexit");
   rmexit($_)  ||  warn "couldnt' unregister exit-sub $_!";

   END {
       print "*** Now performing program-exit processing ***\n";
   }


DESCRIPTION
   The AtExit module provides ANSI-C style exit processing modeled after
   the `atexit()' function in the standard C library (see the atexit(3C)
   manpage). Various exit processing routines may be registered by calling
   `atexit()' and passing it the desired subroutine along with any desired
   arguments. Then, at program-exit time, the subroutines registered with
   `atexit()' are invoked with their given arguments in the *reverse* order
   of registration (last one registered is invoked first). Registering the
   same subroutine more than once will cause that subroutine to be invoked
   once for each registration.

   The `atexit()' function exported by AtExit should be passed a subroutine
   name or reference, optionally followed by the list of arguments with
   which to invoke it at program-exit time. Anonymous subroutine references
   passed to `atexit()' act as "closures" (which are described in the
   perlref manpage). If a subroutine *name* is specified (as opposed to a
   subroutine reference) then, unless the subroutine name has an explicit
   package prefix, it is assumed to be the name of a subroutine in the
   caller's current package. A reference to the specified subroutine is
   obtained, and, if invocation arguments were specified, it is "wrapped
   up" in a closure which invokes the subroutine with the specified
   arguments. The resulting subroutine reference is prepended to the front
   of the `@AtExit::EXIT_SUBS' list of exit-handling subroutines and the
   reference is then returned to the caller (just in case you might want to
   unregister it later using `rmexit()'). If the given subroutine could
   *not* be registered, then the value zero is returned.

   The `rmexit()' function exported by AtExit should be passed one or more
   subroutine references, each of which was returned by a previous call to
   `atexit()'. For each argument given, `rmexit()' will look for it in the
   `@AtExit::EXIT_SUBS' list of exit-handling subroutines and remove the
   first such match from the list. The value returned will be the number of
   subroutines that were successfully unregistered.

   At program-exit time, the `END{}' block in the AtExit module iterates
   over the subroutine references in the `@AtExit::EXIT_SUBS' array and
   invokes each one in turn (each subroutine is removed from the front of
   the queue immediately before it is invoked). Note that the subroutines
   in this queue are invoked in first-to-last order (the *reverse* order in
   which they were registered with `atexit()').

 Invoking `atexit()' and `rmexit()' during program-exit

   The variable `$AtExit::IGNORE_WHEN_EXITING' specifies how calls to
   `atexit()' will be handled if they occur during the time that
   subroutines registered with `atexit()' are being invoked. By default,
   this variable is set to a non-zero value, which causes `atexit()' to
   *ignore* any calls made to it during this time (a value of zero will be
   returned). This behavior is consistent with that of the standard C
   library function of the same name. If desired however, the user may
   enable the registration of subroutines by `atexit()' during this time by
   setting `$AtExit::IGNORE_WHEN_EXITING' to zero or to the empty string.
   Just remember that any subroutines registered with `atexit()' during
   program-exit time will be placed at the *front* of the queue of yet-to-
   be-invoked exit-processing subroutines.

   Regardless of when it is invoked, `rmexit()' will *always* attempt to
   unregister the given subroutines (even when called during program-exit
   processing). Keep in mind however that if it is invoked during program-
   exit processing then it will *fail* to unregister any exit-processing
   subroutines that have *already been invoked* by the `END{}' block in the
   AtExit module (since those subroutine calls have already been removed
   from the `@AtExit::EXIT_SUBS' list).

   The variable `$AtExit::EXITING' may be examined to determine if routines
   registered using `atexit()' are currently in the process of being
   invoked. It will be non-zero if they are and zero otherwise.

NOTES
   The usual Perl way of doing exit processing is through the use of
   `END{}' blocks (see the section on "Package Constructors and
   Destructors" in the perlmod manpage). The AtExit module implements its
   exit processing with an `END{}' block that invokes all the subroutines
   registered by `atexit()' in the array `@AtExit::EXIT_SUBS'. If any other
   `END{}' block processing is specified in the user's code or in any other
   packages it uses, then the order in which the exit processing takes
   place is subject to Perl's rules for the order in which `END{}' blocks
   are processed. This may affect when subroutines registered with
   `atexit()' are invoked with respect to other exit processing that is to
   be performed. In particular, if `atexit()' is invoked from within an
   `END{}' block that executes *after* the `END{}' block in the AtExit
   module, then the corresponding subroutine that was registered will never
   be invoked by the AtExit module's exit-processing code.

 `END{}' block processing order

   `END{}' blocks, including those in other packages, get called in the
   reverse order in which they appear in the code. (`atexit()' subroutines
   get called in the reverse order in which they are registered.) If a
   package gets read via "use", it will act as if the `END{}' block was
   defined at that particular part of the "main" code. Packages read via
   "require" will be executed after the code of "main" has been parsed and
   will be seen last so will execute first (they get executed in the
   context of the package in which they exist).

   It is important to note that `END{}' blocks only get called on normal
   termination (which includes calls to `die()' or `Carp::croak()'). They
   do *not* get called when the program terminates *abnormally* (due to a
   signal for example) unless special arrangements have been made by the
   programmer (e.g. using a signal handler -- see the section on
   "%SIG{expr}" in the perlvar manpage).

SEE ALSO
   the atexit(3C) manpage describes the `atexit()' function for the
   standard C library (the actual Unix manual section in which it appears
   may differ from platform to platform - try sections 3C, 3, 2C, and 2).
   Further information on anonymous subroutines ("closures") may be found
   in the perlref manpage. For more information on `END{}' blocks, see the
   section on "Package Constructors and Destructors" in the perlmod
   manpage. See the section on "%SIG{expr}" in the perlvar manpage for
   handling abnormal program termination.

AUTHOR
   Andrew Langmead <[email protected]> (initial draft).

   Brad Appleton <[email protected]> (final version).