Re: Propogating Errors / E-Toys

2002-07-10 Thread Dave Rolsky

On Wed, 10 Jul 2002, Matt Sergeant wrote:

> Ah, in that case I'm recommending Dave's stuff. It's more flexible and
> doesn't use that irritating -param stuff. Though I have to do a little
> more research to be certain some things are possible (like turning on
> stack traces globally).

Actually, traces are now _always_ created.  And by default they're shown
when stringifying the exception object.

To turn this off you do:

 Exception::Class::Base->Trace(0);

To turn it off for one branch of the hierarchy, do:

 My::Exception::Subclass->Trace(0);

to turn it back on for a branch below that, do:

 My::Exception::Subclass::SubSubClass->Trace(1);

I'm also planning to add some more features to it.

One is something we're using with Mason, where we create convenience subs
for throwing exceptions so we can do:

 param_error "Missing 'foo' in call to new";

instead of:

 HTML::Mason::Exception::Params->throw( error => "Missing 'foo' in call to new" );

plus as an added bonus the first version gets compile time checking of the
sub name, versus runtime checking of the class name in the second.



-dave

/*==
www.urth.org
we await the New Sun
==*/




Re: Propogating Errors / E-Toys

2002-07-10 Thread Matt Sergeant

On Wed, 10 Jul 2002, Perrin Harkins wrote:

> Matt Sergeant wrote:
> > On Wed, 10 Jul 2002, Fran Fabrizio wrote:
> >>Just to confirm, the end result of Matt's slide presentation was that
> >>Error.pm was good, and you should use it, but you should not use the
> >>try/catch syntax, or at the bare minimum only catch in your outermost
> >>handler.  Is that correct?  We were debating this just yesterday in our
> >>office.
> >
> > Actually my recommendation for this year's talk on exceptions is to just
> > use eval{}; if ($@) {}. It's a little more typing, but at the end of the
> > day closures created by subroutine prototypes are a really bad thing (tm).
>
> I believe he was asking if Error.pm is a good class to use for
> exceptions if you don't use the try/catch keywords.  I think it is.  It
> provides handy methods for storing attributes of the exception and
> getting stack traces, and it's easy to subclass.  You could also use
> Dave Rolsky's Exception::Class, which is pretty similar.

Ah, in that case I'm recommending Dave's stuff. It's more flexible and
doesn't use that irritating -param stuff. Though I have to do a little
more research to be certain some things are possible (like turning on
stack traces globally).

-- 

<:->Get a smart net




Re: Propogating Errors / E-Toys

2002-07-10 Thread Perrin Harkins

Matt Sergeant wrote:
> On Wed, 10 Jul 2002, Fran Fabrizio wrote:
>>Just to confirm, the end result of Matt's slide presentation was that
>>Error.pm was good, and you should use it, but you should not use the
>>try/catch syntax, or at the bare minimum only catch in your outermost
>>handler.  Is that correct?  We were debating this just yesterday in our
>>office.
> 
> Actually my recommendation for this year's talk on exceptions is to just
> use eval{}; if ($@) {}. It's a little more typing, but at the end of the
> day closures created by subroutine prototypes are a really bad thing (tm).

I believe he was asking if Error.pm is a good class to use for 
exceptions if you don't use the try/catch keywords.  I think it is.  It 
provides handy methods for storing attributes of the exception and 
getting stack traces, and it's easy to subclass.  You could also use 
Dave Rolsky's Exception::Class, which is pretty similar.

- Perrin




Re: Propogating Errors / E-Toys

2002-07-10 Thread Matt Sergeant

On Wed, 10 Jul 2002, Fran Fabrizio wrote:

>
> Just to confirm, the end result of Matt's slide presentation was that
> Error.pm was good, and you should use it, but you should not use the
> try/catch syntax, or at the bare minimum only catch in your outermost
> handler.  Is that correct?  We were debating this just yesterday in our
> office.

Actually my recommendation for this year's talk on exceptions is to just
use eval{}; if ($@) {}. It's a little more typing, but at the end of the
day closures created by subroutine prototypes are a really bad thing (tm).

-- 

<:->Get a smart net




Re: Propogating Errors / E-Toys

2002-07-10 Thread Fran Fabrizio


Just to confirm, the end result of Matt's slide presentation was that 
Error.pm was good, and you should use it, but you should not use the 
try/catch syntax, or at the bare minimum only catch in your outermost 
handler.  Is that correct?  We were debating this just yesterday in our 
office.

-Fran






Re: Propogating Errors / E-Toys

2002-07-09 Thread Matt Sergeant

On Wed, 10 Jul 2002, Michael Schout wrote:

> Perrin Harkins wrote:
> >
> > We've actually discussed this on the list.  It has to do with closures.
> >  Matt gave a presentation about exception handling which covers it and
> > shows a workaround.  You can see it here:
> >
> > http://axkit.org/docs/presentations/tpc2001/
>
> Sorry to chime in a little late on this.
>
> But the "Exceptions" slides from the page above are either misleading,
> or I am misunderstainding just what exactly leaks in Error.

I didn't say "leaks" in my slides. That's what you're misunderstanding. It
merely creates a closure. This *can* lead to leaks, but doesn't always.

I guess at some point I aught to pick up Error::Filter again. Damn that
hard drive crash (which lost the source code I had for a source filter
version of Error.pm, which didn't create closures).

-- 

<:->Get a smart net




Re: Propogating Errors / E-Toys

2002-07-09 Thread Perrin Harkins

Michael Schout wrote:

> in other words, if I understand the eToys article correctly, the leaks 
> only happen if I nest a try block inside another try block.  I have 
> experimented some, and it appears to me that this is in fact the case 
> ($count doesnt get cleaned up if there is a nested try).  But as long as
> I dont nest try blocks there doesnt appear to be a leak.


You are correct, you won't get a leak from the code in Matt's example. 
 What you will get is an unexpected persistence of the value of the 
$count variable.  It will retain its value and not be reset when you 
enter the handler sub again.

There are other problems too, like "return" not doing what you would 
expect when used inside a try block (it only returns from the try block).

- Perrin




Re: Propogating Errors / E-Toys

2002-07-09 Thread Michael Schout

Perrin Harkins wrote:
> 
> We've actually discussed this on the list.  It has to do with closures. 
>  Matt gave a presentation about exception handling which covers it and 
> shows a workaround.  You can see it here:
> 
> http://axkit.org/docs/presentations/tpc2001/

Sorry to chime in a little late on this.

But the "Exceptions" slides from the page above are either misleading, 
or I am misunderstainding just what exactly leaks in Error.

The slides above show a "BAD" example of Error.pm as:

sub handler {
 my $r = shift;
 my $count;

 try {
 # use $count in here...
 } catch Error with {
 };
}

However, the eToys article doesnt say that this is unsafe.  What the 
eToys article says is unsafe is code with nested try blocks like this:

my $count;
try {
...
try {
 # use $count in *here*
};
};

in other words, if I understand the eToys article correctly, the leaks 
only happen if I nest a try block inside another try block.  I have 
experimented some, and it appears to me that this is in fact the case 
($count doesnt get cleaned up if there is a nested try).  But as long as
I dont nest try blocks there doesnt appear to be a leak.

Are Matt's slides misleading on this point?  Or am I missing something here?

Mike




Re: Propogating Errors / E-Toys

2002-06-30 Thread Perrin Harkins

F. Xavier Noria wrote:
> I remember the article has a comment regarding a gotcha of the Error
> module that causes memory leaks, but you didn't go into details there.

We've actually discussed this on the list.  It has to do with closures. 
  Matt gave a presentation about exception handling which covers it and 
shows a workaround.  You can see it here:

http://axkit.org/docs/presentations/tpc2001/

- Perrin




Re: Propogating Errors / E-Toys

2002-06-30 Thread F . Xavier Noria

On Sun, 30 Jun 2002 12:58:08 -0400
Perrin Harkins <[EMAIL PROTECTED]> wrote:

: Well, naturally the answer is "it depends."  Most database errors can't 
: be gracefully recovered from, so we would let them propagate up.  If it 
: was possible for a database error to be caused by user input (say, a 
: duplicate login name) that would need to be caught and handled.  It 
: would also be caught if any special cleanup of non-database resources 
: was needed.

Excellent message, thank you for sharing those experiences once again!

I remember the article has a comment regarding a gotcha of the Error
module that causes memory leaks, but you didn't go into details there. 
I took note of that and am using eval instead of the try/catch syntax
since I do not understand what the problem is and cannot program
avoiding it for sure... I would appreciate very much if you could give
further details (maybe a pointer somewhere) on what origines the leak
and which was your style writing try/catch blocks once aware of the
problem.

Thanks, and best regards from template Barcelona,

-- fxn



Re: Propogating Errors / E-Toys

2002-06-30 Thread Perrin Harkins

Richard Clarke wrote:
> Using Perrin's article on E-Toys is perhaps a good place to start. In the
> Model object which performs various DB procedures, what actions were taken
> if for some reason the connection to the database failed or if an SQL error
> happened? Was the whole "execute()" block put in an eval procedure and then
> a generic error page produced; Or were either per procedure evals or
> Exception objects used to propogate specific errors up to the control object
> so that it could display errors in the current page/view?

Well, naturally the answer is "it depends."  Most database errors can't 
be gracefully recovered from, so we would let them propagate up.  If it 
was possible for a database error to be caused by user input (say, a 
duplicate login name) that would need to be caught and handled.  It 
would also be caught if any special cleanup of non-database resources 
was needed.

Errors that propagate up are caught by an eval wrapping the whole 
handler method which issues a rollback to the database, logs the error, 
and prints either a pretty error page or a stack trace depending on the 
current debug settings.

Here's an excerpt from the documentation I wrote for our exception base 
class.  This uses the try/catch syntax from Error.pm.

=head1 HANDLING DBI ERRORS

Since DBI errors are the most common source of exceptions in our
application, I'm giving them special treatment here.  Because we are
planning to use the RaiseError option of DBI, you can expect DBI to
die whenever it hits a problem, as opposed to returning an undef value
that you have to check for.  This means that most of the time you
don't need to do anything special for handling DBI errors.  They will
propagate up and be caught at the top level.

DBI exceptions will be propagated as instances of the Error::Simple
class.

You can catch your own exceptions without catching the DBI
exceptions by catching specific classes other than Error::Simple.

   try {
   # lookup password in Oracle
   my $sth = $dbh->prepare_cached($sql_query);
   $sth->execute($bind_value);
   if (!$sth->rows) {
   # should have matched something
   throw ESF::Error::User::BogusPassword -text $password;
   }
   $ary_ref  = $sth->fetchrow_arrayref;
   # ... etc. ...
   }
   catch ESF::Error::User::BogusPassword with {
   # handle this error
   }; # <-- don't forget!

It's okay to use transactions, and to put in your C<$dbh->commit>
statement at the end assuming everything will work.  If DBI throws an
exception that propagates to the top without being caught, we will
automatically issue a C<$dbh->rollback> command.

Sometimes, you may want to catch a specific DBI error.  Be careful
when doing this, because you need to know the error number or text of
the error message in order to trap the right exception.

DBI's raise error setting will cause it to fill the text attribute of
the Error::Simple objects it throws with the message given by Oracle,
so if you want to trap errors of type ORA-172, you can do this:

   try {
   my $sth = $dbh->prepare_cached($sql_query);
   $sth->execute($bind_value);
   }
   catch Error::Simple with {
   my $err = shift;
   if ($err->text() =~ m/ORA-172/) {
   # handle the error here
   } else {
   # let this error propagate
   $err->throw();
   }
   }; # <-- don't forget!


- Perrin




Propogating Errors / E-Toys

2002-06-30 Thread Richard Clarke

List,
Without wanting to fire up a huge thread about MVC seperation etc etc. I
just wondered if someone would share their expertise on the following
question.
Using Perrin's article on E-Toys is perhaps a good place to start. In the
Model object which performs various DB procedures, what actions were taken
if for some reason the connection to the database failed or if an SQL error
happened? Was the whole "execute()" block put in an eval procedure and then
a generic error page produced; Or were either per procedure evals or
Exception objects used to propogate specific errors up to the control object
so that it could display errors in the current page/view?

Richard