X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FSchema.pm;h=84e4e376b128f36ca3819ad3516f01777e7d18fb;hb=2bbdb85a47bab6c27ddf44e0a3a77224ba5242d8;hp=ed219b002bf5d066023da0d5294e88cc3d106151;hpb=e407b4ac86ccfbd6e721d459c04561899a701bac;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Schema.pm b/lib/DBIx/Class/Schema.pm index ed219b0..84e4e37 100644 --- a/lib/DBIx/Class/Schema.pm +++ b/lib/DBIx/Class/Schema.pm @@ -8,7 +8,7 @@ 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); +use DBIx::Class::_Util qw(refcount quote_sub is_exception scope_guard); use Devel::GlobalDestruction; use namespace::clean; @@ -1055,26 +1055,67 @@ default behavior will provide a detailed stack trace. =cut sub throw_exception { - my $self = shift; + my ($self, @args) = @_; if (my $act = $self->exception_action) { - if ($act->(@_)) { - DBIx::Class::Exception->throw( + + my $guard_disarmed; + + my $guard = scope_guard { + return if $guard_disarmed; + local $SIG{__WARN__}; + Carp::cluck(" + !!! DBIx::Class INTERNAL PANIC !!! + +The exception_action() handler installed on '$self' +aborted the stacktrace below via a longjmp (either via Return::Multilevel or +plain goto, or Scope::Upper or something equally nefarious). There currently +is nothing safe DBIx::Class can do, aside from displaying this error. A future +version ( 0.082900, when available ) will reduce the cases in which the +handler is invoked, but this is neither a complete solution, nor can it do +anything for other software that might be affected by a similar problem. + + !!! FIX YOUR ERROR HANDLING !!! + +This guard was activated beginning" + ); + }; + + eval { + # if it throws - good, we'll go down to the do{} below + # 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' - ." (original error: $_[0])" - ); + ." (original error: $args[0])" + ); + } + else { + carp_unique ( + "The exception_action handler installed on $self returned false instead" + .' of throwing an exception. This behavior has been deprecated, adjust your' + .' handler to always rethrow the supplied error' + ); + } + + $guard_disarmed = 1; } - carp_unique ( - "The exception_action handler installed on $self returned false instead" - .' of throwing an exception. This behavior has been deprecated, adjust your' - .' handler to always rethrow the supplied error.' - ); + 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($@); + + $guard_disarmed = 1; + $args[0] = $@; + }; } - DBIx::Class::Exception->throw($_[0], $self->stacktrace); + DBIx::Class::Exception->throw($args[0], $self->stacktrace); } =head2 deploy