File Coverage

blib/lib/AtExit.pm
Criterion Covered Total %
statement 19 72 26.3
branch 1 38 2.6
condition 2 39 5.1
subroutine 6 14 42.8
pod 0 7 0.0
total 28 170 16.4


line stmt bran cond sub pod time code
1             ##############################################################################
2             # AtExit.pm -- a Perl5 module to provide C-style atexit() processing
3             #
4             # Copyright (c) 1996 Andrew Langmead. All rights reserved.
5             # This file is part of "AtExit". AtExit is free software;
6             # This is free software; you can redistribute it and/or modify it under
7             # the terms of the Artistic License 1.0.
8             ##############################################################################
9              
10             package AtExit;
11             $AtExit::VERSION = '2.05';
12             # ABSTRACT: perform exit processing for a program or object
13              
14             require 5.002;
15              
16              
17             =head1 NAME
18              
19             AtExit - perform exit processing for a program or object
20              
21             =head1 SYNOPSIS
22              
23             use AtExit;
24              
25             sub cleanup {
26             my @args = @_;
27             print "cleanup() executing: args = @args\n";
28             }
29            
30             ## Register subroutines to be called when this program exits
31              
32             $_ = atexit(\&cleanup, "This call was registered first");
33             print "first call to atexit() returned $_\n";
34              
35             $_ = atexit("cleanup", "This call was registered second");
36             print "second call to atexit() returned $_\n";
37              
38             $_ = atexit("cleanup", "This call should've been unregistered by rmexit");
39             rmexit($_) or warn "couldnt' unregister exit-sub $_!";
40              
41             if (@ARGV == 0) {
42             ## Register subroutines to be called when this lexical scope is exited
43             my $scope1 = AtExit->new( \&cleanup, "Scope 1, Callback 1" );
44             {
45             ## Do the same for this nested scope
46             my $scope2 = AtExit->new;
47             $_ = $scope2->atexit( \&cleanup, "Scope 2, Callback 1" );
48             $scope1->atexit( \&cleanup, "Scope 1, Callback 2");
49             $scope2->atexit( \&cleanup, "Scope 2, Callback 2" );
50             $scope2->rmexit($_) or warn "couldn't unregister exit-sub $_!";
51              
52             print "*** Leaving Scope 2 ***\n";
53             }
54             print "*** Finished Scope 2 ***\n";
55             print "*** Leaving Scope 1 ***\n";
56             }
57             print "*** Finished Scope 1 ***\n" if (@ARGV == 0);
58              
59             END {
60             print "*** Now performing program-exit processing ***\n";
61             }
62              
63             =head1 DESCRIPTION
64              
65             The B module provides ANSI-C style exit processing modeled after
66             the C function in the standard C library (see L).
67             Various exit processing routines may be registered by calling
68             B and passing it the desired subroutine along with any
69             desired arguments. Then, at program-exit time, the subroutines registered
70             with B are invoked with their given arguments in the
71             I order of registration (last one registered is invoked first).
72             Registering the same subroutine more than once will cause that subroutine
73             to be invoked once for each registration.
74              
75             An B object can be created in any scope. When invoked as a
76             function, B registers callbacks to be
77             executed at I time. But when invoked as an object-method
78             (using the C<$object-Emethod_name> syntax),
79             callbacks registered with an B object are executed at
80             I! The rules for order of execution of the
81             registered subroutines are the same for objects during
82             object-destruction, as for the program during program-termination.
83              
84             The B function/method should be passed a subroutine name or
85             reference, optionally followed by the list of arguments with which to
86             invoke it at program/object exit time. Anonymous subroutine references
87             passed to B act as "closures" (which are described in
88             L). If a subroutine I is specified (as opposed to a
89             subroutine reference) then, unless the subroutine name has an explicit
90             package prefix, it is assumed to be the name of a subroutine in the
91             caller's current package. A reference to the specified subroutine is
92             obtained, and, if invocation arguments were specified, it is "wrapped
93             up" in a closure which invokes the subroutine with the specified
94             arguments. The resulting subroutine reference is added to the front of
95             the list of exit-handling subroutines for the program (C) or
96             the B object (C<$exitObject-Eatexit>) and the reference is
97             then returned to the caller (just in case you might want to unregister
98             it later using B. If the given subroutine could I be
99             registered, then the value zero is returned.
100              
101             The B function/method should be passed one or more subroutine
102             references, each of which was returned by a previous call to
103             B. For each argument given, B will look in the list
104             of exit-handling subroutines for the program (B) or the
105             B object (C<$exitObject-Ermexit>) and remove the first
106             matching entry from the list. If no arguments are given,
107             I
108             The value returned will be the number of subroutines that were
109             successfully unregistered.
110              
111             At object destruction time, the C subroutine in the
112             B module iterates over the subroutine references in the
113             B object and invokes each one in turn (each subroutine is
114             removed from the front of the queue immediately before it is invoked).
115             At program-exit time, the C block in the B module
116             iterates over the subroutines in the array returned by the
117             B method and invokes each one in turn (each subroutine is
118             removed from the front of the queue immediately before it is invoked).
119             Note that in both cases (program-exit, and object-destruction) the
120             subroutines in this queue are invoked in first-to-last order (the
121             I order in which they were registered with B).
122              
123             =head2 Adding and removing callbacks during exit/destruction time.
124              
125             The method B specifies how exit-callback
126             registration and unregistration will be handled during program-exit
127             or object-destruction time, while exit-callbacks are in process
128             of being invoked.
129              
130             When invoked as a class method (e.g., Cignore_when_exiting>),
131             B corresponds to the handling of calls to
132             B and B during program-termination. But when invoked as
133             an I method (e.g., C<$exitObject-Eignore_when_exiting>), then
134             B corresponds to the handling of calls to
135             B and B during I for the particular
136             object.
137              
138             By default, B returns a non-zero value, which
139             causes B to I any calls made to it during this time
140             (a value of zero will be returned). This behavior is consistent with
141             that of the standard C library function of the same name. If desired
142             however, the user may enable the registration of subroutines by
143             B during this time by invoking B and
144             passing it an argument of 0, C<"">, or C (for example,
145             Cignore_when_exiting(0)> or
146             C<$exitObject-Eignore_when_exiting(0)>,
147             Just remember that any subroutines registered with B be
148             placed at the I of the queue of yet-to-be-invoked
149             exit-processing subroutines for the program (B) or the
150             B object (C<$exitObject-Eatexit>).
151              
152             Regardless of when it is invoked, B will I attempt to
153             unregister the given subroutines (even when called during
154             program/object exit processing). Keep in mind however that if it is
155             invoked during program/object exit then it will I to unregister
156             any subroutines that have I (since those
157             subroutine calls have already been removed from the corresponding list
158             of exit-handling subroutines).
159              
160             The method B may consulted examined to determine if
161             routines registered using B are currently in the process of
162             being invoked. It will be non-zero if they are and zero otherwise. When
163             invoked as a class method (e.g., Cis_exiting>), the return
164             value will correspond to program-exit processing; but when invoked as
165             an I method (e.g., C<$exitObject-Eis_exiting>) the return
166             value will correspond to object-destruction processing for the given
167             object.
168              
169             If, for any reason, the list of registered callback needs to be directly
170             accessed or manipulated, the B function will return a reference
171             to the list of program-exit callbacks. When invoked as a method, B
172             will return a reference to the list of object-destruction callbacks for the
173             corresponding object.
174              
175             =head1 EXPORTS
176              
177             For backward compatibility, B and B are exported
178             by default. I however that B, B, and
179             B are I exported by default, and should
180             be invoked as class methods (e.g. Cis_exiting>) if
181             they are to manipulate program-exit information (rather than
182             object-destruction) and not explicitly imported.
183              
184             =head1 CAVEATS
185              
186             =head1 Program-termination and Object-destruction
187              
188             The usual Perl way of doing program/module-exit processing is through
189             the use of C blocks
190             (see L).
191             The B module implements its program-exit processing with with
192             an C block that invokes all the subroutines registered by
193             B in the array whose referenced is returned by C.
194              
195             For an object, object-destruction processing is implemented by having the
196             C method for the object invoke all the subroutines registered
197             by C<$exitObject-Eatexit>. This occurs when the object loses it's
198             last reference, which is not necessarily at program end time.
199              
200             For objects defined in the global context, if any other C block
201             processing is specified in the user's code or in any other packages it
202             uses, then the order in which the exit processing takes place is
203             subject to Perl's rules for the order in which objects loose their last
204             references and C blocks are processed. This may affect when
205             subroutines registered with B are invoked with respect to other
206             exit processing that is to be performed. In particular, if B is
207             invoked from within an C block that executes I the
208             B object was destroyed, then the corresponding subroutine will
209             not be registered and will never be invoked by the B module's
210             destructor code.
211              
212             =head1 C block processing order
213              
214             C blocks, including those in other packages, get called in the
215             reverse order in which they appear in the code. (B subroutines
216             get called in the reverse order in which they are registered.) If a
217             package gets read via "use", it will act as if the C block was
218             defined at that particular part of the "main" code. Packages read via
219             "require" will be executed after the code of "main" has been parsed and
220             will be seen last so will execute first (they get executed in the
221             context of the package in which they exist).
222              
223             It is important to note that C blocks and object destruction
224             only get called on normal termination (which includes calls to B
225             or B). They do I get called when the program
226             terminates I (due to a signal for example) unless special
227             arrangements have been made by the programmer (e.g. using a signal
228             handler -- see L).
229              
230             =head1 SEE ALSO
231              
232             L describes the B function for the standard C
233             library (the actual Unix manual section in which it appears may differ
234             from platform to platform - try sections 3C, 3, 2C, and 2). Further
235             information on anonymous subroutines ("closures") may be found in
236             L. For more information on C blocks, see
237             L. See
238             L for handling abnormal program termination.
239              
240             The following modules all provide similar capability:
241             L,
242             L,
243             L,
244             L,
245             L,
246             L,
247             L,
248             L,
249             L.
250              
251             L provides a similar capability, but it failed to install for me,
252             and was last released in 2003.
253              
254             L lets you provide code to be invoked when a value
255             is destroyed.
256              
257             L will execute your code after the scope finishes
258             I.
259              
260             =head1 REPOSITORY
261              
262             L
263              
264             =head1 COPYRIGHT AND LICENSE
265              
266             This software is copyright (c) 1996 by Brad Appleton.
267              
268             This is free software; you can redistribute it and/or modify it under
269             the terms of the Artistic License 1.0.
270              
271             =head1 AUTHOR
272              
273             Andrew Langmead Eaml@world.std.comE (initial draft).
274              
275             Brad Appleton Ebradapp@enteract.comE (Version 1.02 and 2.00).
276              
277             Michael A. Chase Emchase@ix.netcom.comE (Version 2.00).
278              
279             =cut
280              
281 1         73 use vars qw(
282             @EXIT_SUBS
283             $EXITING
284             $IGNORE_WHEN_EXITING
285 1     1   949 );
  1         3  
286              
287 1     1   6 use strict;
  1         2  
  1         25  
288 1     1   6 use warnings;
  1         2  
  1         34  
289 1     1   4 use Exporter;
  1         2  
  1         1042  
290              
291             our @ISA = qw( Exporter );
292             our @EXPORT = qw( atexit rmexit );
293             our @EXPORT_OK = qw( atexit rmexit exit_subs is_exiting ignore_when_exiting );
294              
295             ## Class/Package-level exit attrs
296             my %EXIT_ATTRS = (
297             'EXIT_SUBS' => [],
298             'EXITING' => 0,
299             'IGNORE_WHEN_EXITING' => 1
300             );
301              
302             ## Aliases to the above for @EXIT_SUBS and $EXITING
303             ## (for backward compatibility)
304             *EXIT_SUBS = $EXIT_ATTRS{EXIT_SUBS};
305             *EXITING = \$EXIT_ATTRS{EXITING};
306             *IGNORE_WHEN_EXITING = \$EXIT_ATTRS{IGNORE_WHEN_EXITING};
307              
308             sub new {
309             ## Determine if we were called via an object-ref or a classname
310 0     0 0 0 my $this = shift;
311 0   0     0 my $class = ref($this) || $this;
312              
313             ## Bless ourselves into the desired class and perform any initialization
314 0         0 my $self = {
315             'EXIT_SUBS' => [],
316             'EXITING' => 0,
317             'IGNORE_WHEN_EXITING' => 1
318             };
319 0         0 bless $self, $class;
320 0 0       0 $self->atexit(@_) if @_;
321 0         0 return $self;
322             }
323              
324             sub exit_subs {
325             ## If called as an object, get the object-ref
326 0 0 0 0 0 0 my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
327              
328 0         0 return $self->{EXIT_SUBS};
329             }
330              
331             sub is_exiting {
332             ## If called as an object, get the object-ref
333 0 0 0 0 0 0 my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
334              
335 0         0 return $self->{EXITING};
336             }
337              
338             sub ignore_when_exiting {
339             ## If called as an object, get the object-ref
340 0 0 0 0 0 0 my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
341              
342             ## Discard the class-name if its the first arg
343 0 0 0     0 unless ($self or @_ == 0) {
344 0         0 local $_ = $_[0];
345 0 0 0     0 shift if (defined $_ and $_ and /[A-Za-z_]/);
      0        
346             }
347              
348 0 0       0 $self->{IGNORE_WHEN_EXITING} = shift if @_;
349 0         0 return $self->{IGNORE_WHEN_EXITING};
350             }
351              
352             sub atexit {
353             ## If called as an object, get the object-ref
354 0     0 0 0 local $_ = ref $_[0];
355 0 0 0     0 my $self = ($_ and $_ ne 'CODE') ? shift : \%EXIT_ATTRS;
356              
357             ## Get the remaining arguments
358 0         0 my ($exit_sub, @args) = @_;
359              
360 0 0 0     0 return 0 if ($self->{EXITING} and $self->{IGNORE_WHEN_EXITING});
361              
362 0 0       0 unless (ref $exit_sub) {
363             ## Caller gave us a sub name instead of a sub reference.
364             ## Need to make sure we have the callers package prefix
365             ## prepended if one wasn't given.
366 0         0 my $pkg = '';
367 0 0       0 $pkg = (caller)[0] . "::" unless $exit_sub =~ /::/o;
368              
369             ## Now turn the sub name into a hard sub reference.
370 0         0 $exit_sub = eval "\\&$pkg$exit_sub";
371 0 0       0 undef $exit_sub if ($@);
372             }
373 0 0 0     0 return 0 unless (defined $exit_sub) && (ref($exit_sub) eq 'CODE');
374              
375             ## If arguments were given, wrap the invocation up in a closure
376 0 0   0   0 my $subref = (@args > 0) ? sub { &$exit_sub(@args); } : $exit_sub;
  0         0  
377              
378             ## Now put this sub-ref on the queue and return what we just registered
379 0         0 unshift(@{ $self->{EXIT_SUBS} }, $subref);
  0         0  
380 0         0 return $subref;
381             }
382              
383             sub rmexit {
384             ## If called as an object, get the object-ref
385 0     0 0 0 local $_ = ref $_[0];
386 0 0 0     0 my $self = ($_ and $_ ne 'CODE') ? shift : \%EXIT_ATTRS;
387              
388             ## Get remaining arguments
389 0         0 my @subrefs = @_;
390              
391             ## Unregister each sub in the given list.
392             ## [ I suppose I could come up with a faster way to do this than
393             ## doing a separate iteration for each argument, but I wont
394             ## worry about that just yet. ]
395             ##
396 0         0 my ($unregistered, $i) = (0, 0);
397 0         0 my $exit_subs = $self->{EXIT_SUBS};
398 0 0       0 if (@subrefs == 0) {
399             ## Remove *all* exit-handlers
400 0         0 $unregistered = scalar(@$exit_subs);
401 0         0 $exit_subs = $self->{EXIT_SUBS} = [];
402             }
403             else {
404 0         0 my $subref;
405 0         0 foreach $subref (@subrefs) {
406 0 0       0 next unless (ref($subref) eq 'CODE');
407             ## Iterate over the queue and remove the first match
408 0         0 for ($i = 0; $i < @$exit_subs; ++$i) {
409 0 0       0 if ($subref == $exit_subs->[$i]) {
410 0         0 splice(@$exit_subs, $i, 1);
411 0         0 ++$unregistered;
412 0         0 last;
413             }
414             }
415             }
416             }
417 0         0 return $unregistered;
418             }
419              
420             sub do_atexit {
421             ## If called as an object, get the object-ref
422 1 50 33 1 0 10 my $self = (@_ and ref $_[0]) ? shift : \%EXIT_ATTRS;
423              
424 1         2 $self->{EXITING} = 1;
425              
426             ## Handle atexit() stuff in reverse order of registration
427 1         3 my $exit_subs = $self->{EXIT_SUBS};
428 1         2 my $subref;
429 1   33     9 while (defined($exit_subs) and @$exit_subs > 0) {
430 0         0 $subref = shift @$exit_subs;
431 0         0 &$subref();
432             }
433              
434 1         27 $self->{EXITING} = 0;
435             }
436              
437             sub DESTROY {
438 0     0     my $self = shift;
439 0           $self->do_atexit();
440 0           return undef;
441             }
442              
443             END {
444 1     1   669 do_atexit();
445             }
446              
447             1;