| 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.04'; | 
| 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 | 
| 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 | 
| 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 |  |  |  |  | 53 | use vars qw( | 
| 282 |  |  |  |  |  |  | @EXIT_SUBS | 
| 283 |  |  |  |  |  |  | $EXITING | 
| 284 |  |  |  |  |  |  | $IGNORE_WHEN_EXITING | 
| 285 | 1 |  |  | 1 |  | 620 | ); | 
|  | 1 |  |  |  |  | 2 |  | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 1 |  |  | 1 |  | 4 | use strict; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 16 |  | 
| 288 | 1 |  |  | 1 |  | 4 | use warnings; | 
|  | 1 |  |  |  |  | 1 |  | 
|  | 1 |  |  |  |  | 20 |  | 
| 289 | 1 |  |  | 1 |  | 3 | use Exporter; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 805 |  | 
| 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 | 6 | 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 |  |  |  |  | 2 | my $exit_subs = $self->{EXIT_SUBS}; | 
| 428 | 1 |  |  |  |  | 1 | my $subref; | 
| 429 | 1 |  | 33 |  |  | 7 | while (defined($exit_subs)  and  @$exit_subs > 0) { | 
| 430 | 0 |  |  |  |  | 0 | $subref = shift @$exit_subs; | 
| 431 | 0 |  |  |  |  | 0 | &$subref(); | 
| 432 |  |  |  |  |  |  | } | 
| 433 |  |  |  |  |  |  |  | 
| 434 | 1 |  |  |  |  | 20 | $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 |  | 527 | do_atexit(); | 
| 445 |  |  |  |  |  |  | } | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | 1; |