use Scalar::Util 'weaken';
use Sub::Name 'subname';
use B 'svref_2object';
+use DBIx::Class::GlobalDestruction;
use namespace::clean;
use base qw/DBIx::Class/;
return $source;
}
-{
- my $global_phase_destroy;
-
- # SpeedyCGI runs END blocks every cycle but keeps object instances
- # hence we have to disable the globaldestroy hatch, and rely on the
- # eval trap below (which appears to work, but is risky done so late)
- END { $global_phase_destroy = 1 unless $CGI::SpeedyCGI::i_am_speedy }
-
- sub DESTROY {
- return if $global_phase_destroy;
-
- my $self = shift;
- my $srcs = $self->source_registrations;
-
- for my $moniker (keys %$srcs) {
- # find first source that is not about to be GCed (someone other than $self
- # holds a reference to it) and reattach to it, weakening our own link
- #
- # during global destruction (if we have not yet bailed out) this will throw
- # which will serve as a signal to not try doing anything else
- if (ref $srcs->{$moniker} and svref_2object($srcs->{$moniker})->REFCNT > 1) {
- local $@;
- eval {
- $srcs->{$moniker}->schema($self);
- 1;
- } or do {
- $global_phase_destroy = 1;
- last;
- };
+my $global_phase_destroy;
+sub DESTROY {
+ return if $global_phase_destroy ||= in_global_destruction;
+ my $self = shift;
+ my $srcs = $self->source_registrations;
+
+ for my $moniker (keys %$srcs) {
+ # find first source that is not about to be GCed (someone other than $self
+ # holds a reference to it) and reattach to it, weakening our own link
+ #
+ # during global destruction (if we have not yet bailed out) this should throw
+ # which will serve as a signal to not try doing anything else
+ # however beware - on older perls the exception seems randomly untrappable
+ # due to some weird race condition during thread joining :(((
+ if (ref $srcs->{$moniker} and svref_2object($srcs->{$moniker})->REFCNT > 1) {
+ local $@;
+ eval {
+ $srcs->{$moniker}->schema($self);
weaken $srcs->{$moniker};
- last;
- }
+ 1;
+ } or do {
+ $global_phase_destroy = 1;
+ };
+
+ last;
}
}
}