You are viewing a plain text version of this content. The canonical link for it is here.
Posted to asp@perl.apache.org by Ross Thomas <ro...@grinfinity.com> on 2002/04/28 20:32:30 UTC

Problems with $SIG{__DIE__} in global.asa

I'm relatively new to Apache::ASP and have been trying to install a __DIE__
handler to catch exceptions thrown deep within code. My aim is to be able to
call die() from anywhere and have it caught in a central location where I
can parse the message and display the appropriate HTML to the user. I
especially want this to work with DBI and RaiseError => 1.

Examining the example global.asa I see this line:

$SIG{__DIE__} = \&Carp::confess;

which looks promising, so I replace it with:

$SIG{__DIE__} = sub {
    $Response->Debug("Testing $_[0]");
    print <<HTML;
<html>
<head><title>argh</title></head>
<body>
<p>something tragic happened</p>
</body>
</html>
HTML
    $Response->Flush();
    $Response->End();
};

This is the only thing in my global.asa. Unfortunately, it never gets
called. I test this with Debug -2 and get this:

----------------------------------------------------------
Errors Output

wibble at index.asp line 6. , /usr/share/perl5/Apache/ASP.pm line 1556

Debug Output

RUN ASP (v2.31) for /var/www/test/index.asp
call srand() post fork
GlobalASA package
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28
global.asa was not cached for
_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30e6b2d3c28
compiling global.asa
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28 _var_www_test__asp_global_asaxa20bc880913eb0dba64ba30e6b2d3c28
exists 1 - asp: Apache::ASP=HASH(0x8438b04); compiled: HASH(0x8445a48);
exists: 1; id:
_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30e6b2d3c28; package:
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28; - --- - exists: 0; mtime: 0;
global.asa routines -
creating dbm for file /var/www/test/.asp/.state/server/internal, db
SDBM_File, serializer: Data::Dumper
creating dbm for file /var/www/test/.asp/.state/server/application, db
SDBM_File, serializer: Data::Dumper
session id from cookie: 0675f8c92a27779896700cfe67aebf8f
refreshing 0675f8c92a27779896700cfe67aebf8f with timeout 1020011987
creating dbm for file
/var/www/test/.asp/.state/06/0675f8c92a27779896700cfe67aebf8f, db SDBM_File,
serializer: Data::Dumper
session not expired - time: 1020010787; timeout: 1020011923;
tieing session 0675f8c92a27779896700cfe67aebf8f
statinc init
stat register of Exporter.pm /usr/share/perl/5.6.1/Exporter.pm Exporter
stat register of Carp.pm /usr/share/perl/5.6.1/Carp.pm Carp
stat register of Errno.pm /usr/lib/perl/5.6.1/Errno.pm Errno
stat register of Time/Local.pm /usr/share/perl/5.6.1/Time/Local.pm
Time::Local
stat register of lib.pm /usr/share/perl/5.6.1/lib.pm lib
stat register of DynaLoader.pm /usr/lib/perl/5.6.1/DynaLoader.pm DynaLoader
stat register of MLDBM/Serializer/Data/Dumper.pm
/usr/share/perl5/MLDBM/Serializer/Data/Dumper.pm
MLDBM::Serializer::Data::Dumper
stat register of Apache/DBI.pm /usr/share/perl5/Apache/DBI.pm Apache::DBI
stat register of Tie/Hash.pm /usr/share/perl/5.6.1/Tie/Hash.pm Tie::Hash
stat register of Apache/ASP.pm /usr/share/perl5/Apache/ASP.pm Apache::ASP
skipping StatINC register of Apache
skipping StatINC register of Apache::Constants
stat register of strict.pm /usr/share/perl/5.6.1/strict.pm strict
stat register of vars.pm /usr/share/perl/5.6.1/vars.pm vars
stat register of Config.pm /usr/lib/perl/5.6.1/Config.pm Config
stat register of Carp/Heavy.pm /usr/share/perl/5.6.1/Carp/Heavy.pm
Carp::Heavy
stat register of Class/Struct.pm /usr/share/perl/5.6.1/Class/Struct.pm
Class::Struct
stat register of MLDBM/Sync/SDBM_File.pm
/usr/share/perl5/MLDBM/Sync/SDBM_File.pm MLDBM::Sync::SDBM_File
stat register of Devel/Symdump.pm /usr/share/perl5/Devel/Symdump.pm
Devel::Symdump
stat register of Data/Dumper.pm /usr/lib/perl/5.6.1/Data/Dumper.pm
Data::Dumper
stat register of Apache/Server.pm /usr/lib/perl5/Apache/Server.pm
Apache::Server
stat register of XSLoader.pm /usr/lib/perl/5.6.1/XSLoader.pm XSLoader
stat register of Digest/MD5.pm /usr/lib/perl5/Digest/MD5.pm Digest::MD5
stat register of Apache/Connection.pm /usr/lib/perl5/Apache/Connection.pm
Apache::Connection
stat register of Exporter/Heavy.pm /usr/share/perl/5.6.1/Exporter/Heavy.pm
Exporter::Heavy
stat register of DBI.pm /usr/lib/perl5/DBI.pm DBI
stat register of MLDBM/Sync.pm /usr/share/perl5/MLDBM/Sync.pm MLDBM::Sync
stat register of Apache/Constants/Exports.pm
/usr/lib/perl5/Apache/Constants/Exports.pm Apache::Constants::Exports
stat register of mod_perl.pm /usr/lib/perl5/mod_perl.pm mod_perl
stat register of warnings/register.pm
/usr/share/perl/5.6.1/warnings/register.pm warnings::register
stat register of warnings.pm /usr/share/perl/5.6.1/warnings.pm warnings
stat register of Apache/Table.pm /usr/lib/perl5/Apache/Table.pm
Apache::Table
stat register of SDBM_File.pm /usr/lib/perl/5.6.1/SDBM_File.pm SDBM_File
stat register of overload.pm /usr/share/perl/5.6.1/overload.pm overload
stat register of MLDBM.pm /usr/share/perl5/MLDBM.pm MLDBM
stat register of Fcntl.pm /usr/lib/perl/5.6.1/Fcntl.pm Fcntl
stat register of AutoLoader.pm /usr/share/perl/5.6.1/AutoLoader.pm
AutoLoader
includes have not changed for script index.asp
parse file index.asp
parsing index.asp
undefing sub
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28::__ASP__var_www_test_index_aspxa20bc880913eb0dba64ba30e6b2d3c28
code CODE(0x8499a68)
compiling into package
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28 subid
[Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba3
0e6b2d3c28::__ASP__var_www_test_index_aspxa20bc880913eb0dba64ba30e6b2d3c28]
Script_OnStart
executing __ASP__var_www_test_index_aspxa20bc880913eb0dba64ba30e6b2d3c28
wibble at index.asp line 6. , /usr/share/perl5/Apache/ASP.pm line 1556
Script_OnEnd
ASP Done Processing - asp: Apache::ASP=HASH(0x8438b04);
errors out <li> wibble at index.asp line 6. , /usr/share/perl5/Apache/ASP.pm
line 1556

ASP to Perl Script

  -: package
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28; ;; sub
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28::__ASP__var_www_test_index_aspxa20bc880913eb0dba64ba30e6b2d3c28
{  ;; package
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28; ;; use strict;;use vars qw($Application $Session $Response
$Server $Request);;use lib qw(/var/www/test/.asp);;;
  -: #line 1 index.asp
  1: ; &ASP::WriteRef($main::Response, \('<html>
  2: <head>
  3: <title>Don\'t see me</title>
  4: </head>
  5: <body>
  6: ')); die "wibble" ; &ASP::WriteRef($main::Response, \('
  7: </body>
  8: </html>'));;;no lib qw(/var/www/test/.asp); ;; }
----------------------------------------------------------

As you can see, my custom handler was apparently never called. The same
thing happens if I define an actual subroutine and assign a reference to it
instead of using an anonymous sub.

When I move the $SIG{__DIE__} = sub { ... }; assignment into Script_OnStart,
it *does* get called, but I get this output:

----------------------------------------------------------
something tragic happened

Errors Output

Can't find label APACHE_ASP_EXECUTE_END at /usr/share/perl5/Apache/ASP.pm
line 3627. , /usr/share/perl5/Apache/ASP.pm line 1556

Debug Output

[index.asp] - Testing wibble at index.asp line 6.
Can't find label APACHE_ASP_EXECUTE_END at /usr/share/perl5/Apache/ASP.pm
line 3627. , /usr/share/perl5/Apache/ASP.pm line 1556

ASP to Perl Script

  -: package
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28; ;; sub
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28::__ASP__var_www_test_index_aspxa20bc880913eb0dba64ba30e6b2d3c28
{  ;; package
Apache::ASP::Compiles::_var_www_test__asp_global_asaxa20bc880913eb0dba64ba30
e6b2d3c28; ;; use strict;;use vars qw($Application $Session $Response
$Server $Request);;use lib qw(/var/www/test/.asp);;;
  -: #line 1 index.asp
  1: ; &ASP::WriteRef($main::Response, \('<html>
  2: <head>
  3: <title>Don\'t see me</title>
  4: </head>
  5: <body>
  6: ')); die "wibble" ; &ASP::WriteRef($main::Response, \('
  7: </body>
  8: </html>'));;;no lib qw(/var/www/test/.asp); ;; }
----------------------------------------------------------

Is one not supposed to call $Response->End() from a __DIE__ handler? Am I
missing something obvious?

Some info:

----------------------------------------------------------
$ uname -a
Linux woody 2.4.18 #1 Sun Mar 3 12:10:47 EST 2002 i686 unknown

$ /usr/sbin/apache-perl -V
Server version: Apache/1.3.24 (Unix) Debian GNU/Linux
Server built:   Apr 13 2002 18:07:20
Server's Module Magic Number: 19990320:11
Server compiled with....
 -D EAPI
 -D HAVE_MMAP
 -D HAVE_SHMGET
 -D USE_SHMGET_SCOREBOARD
 -D USE_MMAP_FILES
 -D HAVE_FCNTL_SERIALIZED_ACCEPT
 -D HAVE_SYSVSEM_SERIALIZED_ACCEPT
 -D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
 -D HTTPD_ROOT="/usr"
 -D SUEXEC_BIN="/usr/lib/apache/suexec"
 -D DEFAULT_PIDLOG="/var/run/apache-perl.pid"
 -D DEFAULT_SCOREBOARD="/var/run/apache-perl.scoreboard"
 -D DEFAULT_LOCKFILE="/var/run/apache-perl.lock"
 -D DEFAULT_XFERLOG="/var/log/apache-perl/access.log"
 -D DEFAULT_ERRORLOG="/var/log/apache-perl/error.log"
 -D TYPES_CONFIG_FILE="/etc/mime.types"
 -D SERVER_CONFIG_FILE="/etc/apache-perl/httpd.conf"
 -D ACCESS_CONFIG_FILE="/etc/apache-perl/access.conf"
 -D RESOURCE_CONFIG_FILE="/etc/apache-perl/srm.conf"

$ /usr/sbin/apache-perl -l
Compiled-in modules:
  http_core.c
  mod_so.c
  mod_perl.c
  mod_macro.c
suexec: enabled; valid wrapper /usr/lib/apache/suexec
----------------------------------------------------------

Apache::ASP is version 2.31.

Thanks in advance for any help you can offer.

Regards,
Ross Thomas

: "We dance round in a ring and suppose,
: but the secret sits in the middle and knows" - Robert Frost



---------------------------------------------------------------------
To unsubscribe, e-mail: asp-unsubscribe@perl.apache.org
For additional commands, e-mail: asp-help@perl.apache.org


Re: Problems with $SIG{__DIE__} in global.asa

Posted by Ross Thomas <ro...@grinfinity.com>.
Joshua Chamas wrote:

> Genearlly, you just have a ErrorDocument that covers 500 internal
> server errors, and tell the end user something generic.  These
> kinds of die() errors are fatal system errors so perhaps the
> end user should not see them anyway, else you could just trap
> the error in an eval{} and look at $@ normally.

I was thinking more along the lines of using die() as a kind of
exception-throwing mechanism, but as you point out this is conceptually
flawed since die() is meant for serious unrecoverable errors.

The main reason I wanted it is because DBI is much nicer to use (laziness
being, of course, one of the virtues) with RaiseError => 1, but then any
problem with the database results in a die() that seems untrappable (at
least in the way I want to do it). This is fine when one is talking about,
say, a SELECT containing a syntax error, which is a serious problem and
deserves a 500.

However, in the application I'm currently working on almost all of the
business logic is carried out in custom PostgreSQL server-side functions
which raise exceptions such as "insufficient funds." I like to put a lot of
sanity-checking in database triggers, and so either one has to duplicate
much of that code in Perl (time-consuming and error-prone) or one has to
trap the exceptions and handle them differently to generic database errors.

I eventually discovered DBI's HandleError mechanism, which allows me to give
it a reference to a subroutine that it calls instead of dying. This iis the
perfect solution to my problem, since I can trap the server-side exceptions,
parse the DBI error message, and either produce nice output for the user or
give a 500.

By the way, not only is Apache::ASP by far the best implementation of
embedded Perl available (and I've tried most of them), but the documentation
is extensive and the support you give its users is top-notch.
Congratulations on a superb job.

Regards,
Ross Thomas

P.S. In the documentation of XMLSubsMatch you might want to mention that
using the regular expression "my:.+" is an exceptionally bad idea ;)  I
must've been having a brain freeze...



---------------------------------------------------------------------
To unsubscribe, e-mail: asp-unsubscribe@perl.apache.org
For additional commands, e-mail: asp-help@perl.apache.org


Re: Problems with $SIG{__DIE__} in global.asa

Posted by Joshua Chamas <jo...@chamas.com>.
Ross Thomas wrote:
> 
> I'm relatively new to Apache::ASP and have been trying to install a __DIE__
> handler to catch exceptions thrown deep within code. My aim is to be able to
> call die() from anywhere and have it caught in a central location where I
> can parse the message and display the appropriate HTML to the user. I
> especially want this to work with DBI and RaiseError => 1.
> ...
> As you can see, my custom handler was apparently never called. The same
> thing happens if I define an actual subroutine and assign a reference to it
> instead of using an anonymous sub.
> 
> When I move the $SIG{__DIE__} = sub { ... }; assignment into Script_OnStart,
> it *does* get called, but I get this output:
> 
> ----------------------------------------------------------
> something tragic happened
> 
> Errors Output
> 
> Can't find label APACHE_ASP_EXECUTE_END at /usr/share/perl5/Apache/ASP.pm
> line 3627. , /usr/share/perl5/Apache/ASP.pm line 1556
> 

I tried to get around this problem just now, but could not.  

$Response->End() uses a goto internally to jump to the end of 
the request cycle just before Script_OnEnd ( in 2.33 at least ).
A die() seems to loose track of goto symbols like APACHE_ASP_EXECUTE_END 
even in a $SIG{__DIE__} so you cannot $Response->End() in a die()
handler.

I do not know what to recommend.  You could try overriding die() locally
itself, but I do not think you will get much mileage with that technique.

Genearlly, you just have a ErrorDocument that covers 500 internal
server errors, and tell the end user something generic.  These
kinds of die() errors are fatal system errors so perhaps the 
end user should not see them anyway, else you could just trap
the error in an eval{} and look at $@ normally.

If you want to consistently render an error for things you know
you can catch, you can try an eval in each of your scripts:

eval { ... some code ... };
if($@) { pretty_format($@) };
sub pretty_format { ...; $Response->End; }

One problem you would find is that if you do trap $SIG{__DIE__}
and use 3rd party modules that are catching their own errors
in eval, you may screw up their behavior when looking at $@
to decide what to do next, so I would not recommend overriding
$SIG{__DIE__} like this anyway.  Such a module might protect
its die() by doing a local $SIG{__DIE__} = sub { die(@_ }, so 
maybe this is less of a concern.

--Josh
_________________________________________________________________
Joshua Chamas                           Chamas Enterprises Inc.
NodeWorks Founder                       Huntington Beach, CA  USA 
http://www.nodeworks.com                1-714-625-4051

---------------------------------------------------------------------
To unsubscribe, e-mail: asp-unsubscribe@perl.apache.org
For additional commands, e-mail: asp-help@perl.apache.org