Expand ASSERT_NO_SPURIOUS_EXCEPTION_ACTION to set a rogue $SIG{__DIE__}
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Schema.pm
index f6777d4..7527ddf 100644 (file)
@@ -8,7 +8,10 @@ use base 'DBIx::Class';
 use DBIx::Class::Carp;
 use Try::Tiny;
 use Scalar::Util qw/weaken blessed/;
-use DBIx::Class::_Util qw(refcount quote_sub is_exception scope_guard);
+use DBIx::Class::_Util qw(
+  refcount quote_sub scope_guard
+  is_exception dbic_internal_try
+);
 use Devel::GlobalDestruction;
 use namespace::clean;
 
@@ -191,7 +194,7 @@ sub _ns_get_rsrc_instance {
   my $me = shift;
   my $rs_class = ref ($_[0]) || $_[0];
 
-  return try {
+  return dbic_internal_try {
     $rs_class->result_source_instance
   } catch {
     $me->throw_exception (
@@ -803,7 +806,7 @@ sub connection {
 
   $storage_class =~ s/^::/DBIx::Class::Storage::/;
 
-  try {
+  dbic_internal_try {
     $self->ensure_class_loaded ($storage_class);
   }
   catch {
@@ -1057,7 +1060,11 @@ default behavior will provide a detailed stack trace.
 sub throw_exception {
   my ($self, @args) = @_;
 
-  if (my $act = $self->exception_action) {
+  if (
+    ! DBIx::Class::_Util::in_internal_try()
+      and
+    my $act = $self->exception_action
+  ) {
 
     my $guard_disarmed;
 
@@ -1082,13 +1089,13 @@ This guard was activated beginning"
     };
 
     eval {
-      # if it throws - good, we'll go down to the do{} below
+      # if it throws - good, we'll assign to @args in the end
       # if it doesn't - do different things depending on RV truthiness
       if( $act->(@args) ) {
         $args[0] = (
           "Invocation of the exception_action handler installed on $self did *not*"
         .' result in an exception. DBIx::Class is unable to function without a reliable'
-        .' exception mechanism, ensure that exception_action does not hide exceptions'
+        .' exception mechanism, ensure your exception_action does not hide exceptions'
         ." (original error: $args[0])"
         );
       }
@@ -1100,19 +1107,19 @@ This guard was activated beginning"
         );
       }
 
-      $guard_disarmed = 1;
+      1;
     }
 
       or
 
-    do {
-      # We call this to get the necessary warnings emitted and disregard the RV
-      # as it's definitely an exception if we got as far as this do{} block
-      is_exception($@);
+    # We call this to get the necessary warnings emitted and disregard the RV
+    # as it's definitely an exception if we got as far as this do{} block
+    is_exception(
+      $args[0] = $@
+    );
 
-      $guard_disarmed = 1;
-      $args[0] = $@;
-    };
+    # Done guarding against https://github.com/PerlDancer/Dancer2/issues/1125
+    $guard_disarmed = 1;
   }
 
   DBIx::Class::Exception->throw( $args[0], $self->stacktrace );
@@ -1233,14 +1240,12 @@ format.
 sub ddl_filename {
   my ($self, $type, $version, $dir, $preversion) = @_;
 
-  require File::Spec;
-
   $version = "$preversion-$version" if $preversion;
 
   my $class = blessed($self) || $self;
   $class =~ s/::/-/g;
 
-  return File::Spec->catfile($dir, "$class-$version-$type.sql");
+  return "$dir/$class-$version-$type.sql";
 }
 
 =head2 thaw
@@ -1401,7 +1406,7 @@ sub _register_source {
   return $source if $params->{extra};
 
   my $rs_class = $source->result_class;
-  if ($rs_class and my $rsrc = try { $rs_class->result_source_instance } ) {
+  if ($rs_class and my $rsrc = dbic_internal_try { $rs_class->result_source_instance } ) {
     my %map = %{$self->class_mappings};
     if (
       exists $map{$rs_class}
@@ -1443,6 +1448,7 @@ sub DESTROY {
     # however beware - on older perls the exception seems randomly untrappable
     # due to some weird race condition during thread joining :(((
     if (length ref $srcs->{$source_name} and refcount($srcs->{$source_name}) > 1) {
+      local $SIG{__DIE__} if $SIG{__DIE__};
       local $@;
       eval {
         $srcs->{$source_name}->schema($self);
@@ -1455,6 +1461,11 @@ sub DESTROY {
       last;
     }
   }
+
+  # Dummy NEXTSTATE ensuring the all temporaries on the stack are garbage
+  # collected before leaving this scope. Depending on the code above, this
+  # may very well be just a preventive measure guarding future modifications
+  undef;
 }
 
 sub _unregister_source {
@@ -1511,7 +1522,7 @@ sub compose_connection {
   carp_once "compose_connection deprecated as of 0.08000"
     unless $INC{"DBIx/Class/CDBICompat.pm"};
 
-  try {
+  dbic_internal_try {
     require DBIx::Class::ResultSetProxy;
   }
   catch {