Hi,I've just run into a serious flaw with CGI::Application which completely breaks my exception handling.
I'm setting up a mod_perl system using C::A, and have a handler() that looks like this:
sub handler : method {
my($class, $r) = @_;
local $SIG{__DIE__} = \&catcher;
eval {
my $app = $class->new(QUERY => MyQuery->new($r));
$app->run();
};
return suppressed>handler($r) if $@;
return OK;
}
The catcher() method there installs a local() $SIG{__DIE__} handler that
converts any "uncaught" exceptions raised from within the $app into
instances of my own exception class (a sub-class of Exception::Class); I
can then simply invoke that class' handler() method on the exception
object if any exception was raised.
I have two major problems with C::A in trying to do this:1. It installs CGI-Carp by default which wreaks havoc with the whole scheme of things by playing around with $SIG{__DIE__} and/or CORE::GLBOAL::die() (the latest version of CGI.pm does both in some setups!).
I've carped on about this before. I think the best solution is to have a new import() option asking C::A to not use CGI-Carp, but leave the default behaviour unchanged for backwards compatibility.
2. It executes the run-mode within an eval {} block of its own, catches any exceptions raised and then simply throws them again after having added a bit to them ("Error executing run mode...").
This makes the gross presumption that the run-mode didn't raise an exception *object*. If it did, then it just gets stringified into C::A's string error before getting thrown again. Thus, every exception that I ever raise myself gets caught, stringified and rethrown. My catcher() method catches it, of course, but I now find that *all* my exception objects have become "uncaught [string] exceptions" that my catcher() has caught. There is no point in any of the Exception::Classes that I've been carefully building!
Why bother catching the exception at all, just to throw it again? There's no point unless you're going to *do* something with it in some circumstances. Simply prepending a string to it just screws it up when it's an object. You could catch the exception and prepend a string only if it is already a string (not an object), but even then you're screwing up Exception::Class' record of where the exception was thrown from.
The attached patch (against 3.1) fixes both of these things. PLEEEEEASE can we have this patch, or something equivalent, applied? Hopefully, - Steve
--- Application.pm.orig 2003-06-02 13:43:18.000000000 +0100
+++ Application.pm 2003-09-15 10:31:09.734713000 +0100
@@ -7,7 +7,18 @@
$CGI::Application::VERSION = '3.1';
-use CGI::Carp;
+sub import {
+ my $cgicarp = 1;
+ foreach (@_) { $cgicarp = 0 if /^-nocgicarp$/io }
+ if ($cgicarp) {
+ require CGI::Carp;
+ CGI::Carp->import();
+ }
+ else {
+ require Carp;
+ Carp->import();
+ }
+}
###################################
@@ -139,8 +150,7 @@
}
# Process run mode!
- my $body = eval { $autoload_mode ? $self->$rmeth($rm) : $self->$rmeth() };
- die "Error executing run mode '$rm': $@" if $@;
+ my $body = $autoload_mode ? $self->$rmeth($rm) : $self->$rmeth();
# Support scalar-ref for body return
my $bodyref = (ref($body) eq 'SCALAR') ? $body : \$body;
---------------------------------------------------------------------
Web Archive: http://www.mail-archive.com/suppressed/
http://marc.theaimsgroup.com/?l=cgiapp&r=1&w=2
To unsubscribe, e-mail: suppressed
For additional commands, e-mail: suppressed
Mail converted by mhonarc 2.6.15
This archive provided courtesy of JSW4.NET, Internet Hosting Services for Small Business.