1 package Devel::GlobalDestruction;
8 use Sub::Exporter -setup => {
9 exports => [ qw(in_global_destruction) ],
10 groups => { default => [ -all ] },
13 if (defined ${^GLOBAL_PHASE}) {
14 eval 'sub in_global_destruction () { ${^GLOBAL_PHASE} eq q[DESTRUCT] }';
18 XSLoader::load(__PACKAGE__, $VERSION);
21 # the eval already installed everything, nothing to do
25 # SpeedyCGI runs END blocks every cycle but somehow keeps object instances
27 die("The pure-perl version of @{[__PACKAGE__]} can not function correctly under CGI::SpeedyCGI. "
28 . "Please ensure you have a working compiler, and reinstall @{[__PACKAGE__]} to enable the XS "
30 ) if $CGI::SpeedyCGI::i_am_speedy;
32 eval <<'PP_IGD' or die $@;
34 my ($in_global_destruction, $before_is_installed);
36 sub in_global_destruction { $in_global_destruction }
39 $in_global_destruction = 1;
42 # threads do not execute the global ENDs (it would be stupid). However
43 # one can register a new END via simple string eval within a thread, and
44 # achieve the same result. A logical place to do this would be CLONE, which
45 # is claimed to run in the context of the new thread. However this does
46 # not really seem to be the case - any END evaled in a CLONE is ignored :(
47 # Hence blatantly hooking threads::create
49 if ($INC{'threads.pm'}) {
50 my $orig_create = threads->can('create');
51 no warnings 'redefine';
52 *threads::create = sub {
53 { local $@; eval 'END { $in_global_destruction = 1 }' };
56 $before_is_installed = 1;
59 # just in case threads got loaded after us (silly)
61 unless ($before_is_installed) {
63 Carp::croak("You must load the 'threads' module before @{[ __PACKAGE__ ]}");
73 1; # keep require happy
80 Devel::GlobalDestruction - Expose the flag which marks global
86 use Devel::GlobalDestruction;
88 use namespace::clean; # to avoid having an "in_global_destruction" method
91 return if in_global_destruction;
93 do_something_a_little_tricky();
98 Perl's global destruction is a little tricky to deal with WRT finalizers
99 because it's not ordered and objects can sometimes disappear.
101 Writing defensive destructors is hard and annoying, and usually if global
102 destruction is happenning you only need the destructors that free up non
103 process local resources to actually execute.
105 For these constructors you can avoid the mess by simply bailing out if global
106 destruction is in effect.
110 This module uses L<Sub::Exporter> so the exports may be renamed, aliased, etc.
114 =item in_global_destruction
116 Returns true if the interpreter is in global destruction. In perl 5.14+, this
117 returns C<${^GLOBAL_PHASE} eq 'DESTRUCT'>, and on earlier perls, it returns the
118 current value of C<PL_dirty>.
124 Yuval Kogman E<lt>nothingmuch@woobling.orgE<gt>
126 Florian Ragwitz E<lt>rafl@debian.orgE<gt>
128 Jesse Luehrs E<lt>doy@tozt.netE<gt>
130 Peter Rabbitson E<lt>ribasushi@cpan.orgE<gt>
134 Copyright (c) 2008 Yuval Kogman. All rights reserved
135 This program is free software; you can redistribute
136 it and/or modify it under the same terms as Perl itself.