You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Stas Bekman <st...@stason.org> on 2004/04/29 20:56:05 UTC

[mp2] a new exceptions handling proposal

I was very unhappy about the current status of exceptions handling, so I kept 
on trying to find a nice solution. Here is what I came up with. I hope it 
works for you too.

Returning status codes and handling them makes your code very messy,
especially if you want to prototype something. If we croak on error,
then you can catch it in eval, but there is a problem - you don't want
to match the error message, but the status code. For example if the
exception on read is APR_TIMEUP you won't to be able to access that
code. So here is what I propose that we use for exception
handling. Let's say that apr_status_t is APR_TIMEUP, I'll hardcode it
for this example:

     status = APR_TIMEUP;
     char *err = modperl_apr_strerror(status);
     SV *errsv = get_sv("@", TRUE);
     sv_setpv(errsv, err);
     SvIVX(errsv) = status;
     SvIOK_on(errsv);
     Perl_croak(aTHX_ Nullch);

I couldn't show it in pure perl, since die $err, where $err is a dual object 
doesn't make it through -- perl copies the IV slot only. But it works fine from C.

Basically it's somewhat similar to exception handling with objects,
but here we use a dualvar $@ instead.

So you can write your code without any error handling:

   $socket->recv($buff, $rlen);

And if something goes wrong, Perl will automatically croak for you,
using the full message:

   [Thu Apr 29 11:33:54 2004] [error] 70007:The timeout specified has expired

Though if you decide to catch it, you can do this:

   eval { $socket->recv($buff, $rlen) };
   if ($@) {
        if ($@ == APR::TIMEUP) {
            warn "timed out, giving up";
        }
        else {
            die $@; # rethrow, unhandled error
        }
    }

$@ in the numerical context gives us what we at the moment return, in
the string context it's APR::strerror($rc);

So IMHO this proposal gives us the best of all aspects:

- You can code w/o any error handling, and no silent errors will ever
   occur. I like this more than current perl's core functions which won't
   croak unless you checked the error.

- You can still trap the errors and access the raw numerical return
   code for comparison against error constants

- You get the stringification of the error w/o needing to call
   APR::strerror($rc);

- We no longer need to return the status from each function and can
   make the APIs more perlish.

- We use a commonly known variable $@, which works exactly the same as
   with any other program, but has a special IV value.

- Finally the API is going to be consistent.

- One exception is for functions that may still need to return status
   codes, which aren't errors (but nothing comes to my mind at the moment,
   besides APR::EOF, which we can handle similar to perl's read, i.e.
   returning 0 when there is nothing to read.)

One issue I can see so far is that an uncaught croak:

   [Thu Apr 29 11:33:54 2004] [error] 70007:The timeout specified has expired

doesn't report the context (file/line), so I'm going to figure out how to add 
it manually and it should be fine.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

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


Re: [mp2] a new exceptions handling proposal

Posted by Stas Bekman <st...@stason.org>.
Steve Hay wrote:
> Stas Bekman wrote:
> 
> 
>>So, next I'm trying to use exception objects with overloaded methods. Here is 
>>a demo, this time in perl:
>>
>>package Err;
>>
>>use overload
>>    'bool' => \&num,
>>    '=='   => \&num,
>>    '0+'   => \&num,
>>    '""'   => \&str;
>>
>>sub str { my $self = shift; $self->{str};}
>>sub num { my $self = shift; $self->{num};}
>>
>>sub new {
>>    my ($class, $num, $str) = @_;
>>    bless {
>>        num => $num,
>>        str => $str,
>>    }, __PACKAGE__;
>>
>>}
>>
> 
> This is beginning to look a lot like the Exception::Class module.  I use 
> that module myself for exception handling, and it seems pretty good.  It 
> has a couple of operator overloads in it, but not all that you have 
> above.  However, using E::C involves subclassing it: typically, one has 
> many subclasses, all derived from a single class which is itself derived 
> from E::C::Base, so you could either add the extra overloads to some 
> E::C::ModPerl class, or even suggest them as patches to E::C itself.
> 
> Just trying to save a bit of wheel re-invention ;)

Thanks Steve,

There is not much reinvention going on here, all the above code is all that we 
need. Our model is much simpler and E::C seems like an overkill to me at the 
moment. The idea of (now) APR::Error is to be transparent to the user +$@ 
gives the $rc (that's why we overload == and 0+ ops) and "$@" gives you the 
stringified error, same as $! works. You don't need to be aware of the fact 
that $@ is now an object (besides doing the checking of ref $@).

If in the future we decide that we need E::C functionality, nothing stops us 
from moving to it, keep the code working as before.

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

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


Re: [mp2] a new exceptions handling proposal

Posted by Steve Hay <st...@uk.radan.com>.
Stas Bekman wrote:

>So, next I'm trying to use exception objects with overloaded methods. Here is 
>a demo, this time in perl:
>
>package Err;
>
>use overload
>     'bool' => \&num,
>     '=='   => \&num,
>     '0+'   => \&num,
>     '""'   => \&str;
>
>sub str { my $self = shift; $self->{str};}
>sub num { my $self = shift; $self->{num};}
>
>sub new {
>     my ($class, $num, $str) = @_;
>     bless {
>         num => $num,
>         str => $str,
>     }, __PACKAGE__;
>
>}
>
This is beginning to look a lot like the Exception::Class module.  I use 
that module myself for exception handling, and it seems pretty good.  It 
has a couple of operator overloads in it, but not all that you have 
above.  However, using E::C involves subclassing it: typically, one has 
many subclasses, all derived from a single class which is itself derived 
from E::C::Base, so you could either add the extra overloads to some 
E::C::ModPerl class, or even suggest them as patches to E::C itself.

Just trying to save a bit of wheel re-invention ;)

- Steve



------------------------------------------------
Radan Computational Ltd.

The information contained in this message and any files transmitted with it are confidential and intended for the addressee(s) only.  If you have received this message in error or there are any problems, please notify the sender immediately.  The unauthorized use, disclosure, copying or alteration of this message is strictly forbidden.  Note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of Radan Computational Ltd.  The recipient(s) of this message should check it and any attached files for viruses: Radan Computational will accept no liability for any damage caused by any virus transmitted by this email.


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


Re: [mp2] a new exceptions handling proposal

Posted by Stas Bekman <st...@stason.org>.
Stas Bekman wrote:
> Geoffrey Young wrote:
> 
>>>  Argument "foo ..." isn't numeric ...
>>>
>>> since normally $@ doesn't have the IV slot populated. 
>>
>>
>>
>> can we set the iv slot in ERRSV to 0 at some convenient place, like at 
>> the
>> top of modperl_callback()?
> 
> 
> We can, but it won't do any good, if a non-modperl call fails and resets 
> it.

In any case, objects are good since we need to store more than just rc. The 
way die works, if you don't let it generate the error message on its own, you 
don't get the file/line trace and when you try to print it, you don't have it 
anymore. So you want to store file/line in the object too. So I'm now able to 
generate the short trace (error at file x line y). Now I'm trying to figure 
out how to get things like Carp::confess in SIG{__DIE__} produce a useful info.

Using a dual var $@ is exactly the same as using exception object, since perl 
simply doesn't do anything about it and simply gives it to the user back if 
trapped in eval, or calles die "$@\n" if non-trapped.

-- 
__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

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


Re: [mp2] a new exceptions handling proposal

Posted by Stas Bekman <st...@stason.org>.
Geoffrey Young wrote:
>>  Argument "foo ..." isn't numeric ...
>>
>>since normally $@ doesn't have the IV slot populated. 
> 
> 
> can we set the iv slot in ERRSV to 0 at some convenient place, like at the
> top of modperl_callback()?

We can, but it won't do any good, if a non-modperl call fails and resets it.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

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


Re: [mp2] a new exceptions handling proposal

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
>   Argument "foo ..." isn't numeric ...
> 
> since normally $@ doesn't have the IV slot populated. 

can we set the iv slot in ERRSV to 0 at some convenient place, like at the
top of modperl_callback()?

--Geoff

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


Re: [mp2] a new exceptions handling proposal

Posted by Stas Bekman <st...@stason.org>.
Geoffrey Young wrote:
>>Though if you decide to catch it, you can do this:
>>
>>  eval { $socket->recv($buff, $rlen) };
>>  if ($@) {
>>       if ($@ == APR::TIMEUP) {
>>           warn "timed out, giving up";
>>       }
>>       else {
>>           die $@; # rethrow, unhandled error
>>       }
>>   }

I wrote a bunch of code and it works perfectly well, when there is an error. 
However if you do:

eval {
   some_other_call();
   $socket->recv($buff, $rlen) };
}
die "$@" if $@ && $@ == APR::TIMEUP;

and some_other_call() throws a plain perl exception (die "foo"), we have a 
problem, as the above code will generate:

   Argument "foo ..." isn't numeric ...

since normally $@ doesn't have the IV slot populated. While we could still 
proceed with it and say that it works only for one call eval {}, it's not too 
nice for the users.

So, next I'm trying to use exception objects with overloaded methods. Here is 
a demo, this time in perl:

package Err;

use overload
     'bool' => \&num,
     '=='   => \&num,
     '0+'   => \&num,
     '""'   => \&str;

sub str { my $self = shift; $self->{str};}
sub num { my $self = shift; $self->{num};}

sub new {
     my ($class, $num, $str) = @_;
     bless {
         num => $num,
         str => $str,
     }, __PACKAGE__;

}

package main;

sub foo {
     my $name = shift;
     my $err = Err->new(1234, "$name, stay cool!");
     die $err;
}

eval { foo('gozer'); };
if ($@ && ref $@ && $@ == 1234) {
     warn "The error was: $@";
}

foo('geoff');

so, running it produces:

% perl-5.8.4-ithread proto2.pl
The error was: gozer, stay cool! at proto2.pl line 31.
geoff, stay cool!

As you can see, what happens is, if you don't trap the exception the reloaded 
stringification operator dumps the full error message (I'm planning to 
generate it on demand, rather then populate it when the error occurs). And 
yes, I still miss the line/file info, but it'll be there.

If you trap the exception, you can now certainly know whether this is a 
mod_perl $@ exception (by calling ref()), before doing $@ == 1234, which in 
turn invokes the overloaded numerical methods and gives us the return status 
as a number.

Moreover by using the object we may do even more things in the future.

As by now I've found that all my attempts have stumbled into some kind of 
wall, I'm not 100% sure that this is the perfect solution, but I'm going to 
give it a try next.

As always, your comments and ideas are welcome.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

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


Re: [mp2] a new exceptions handling proposal

Posted by Geoffrey Young <ge...@modperlcookbook.org>.
> Though if you decide to catch it, you can do this:
> 
>   eval { $socket->recv($buff, $rlen) };
>   if ($@) {
>        if ($@ == APR::TIMEUP) {
>            warn "timed out, giving up";
>        }
>        else {
>            die $@; # rethrow, unhandled error
>        }
>    }

+1

--Geoff

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


Re: [mp2] a new exceptions handling proposal

Posted by Stas Bekman <st...@stason.org>.
Matt Sergeant wrote:
> On 29 Apr 2004, at 19:56, Stas Bekman wrote:
> 
>>     SV *errsv = get_sv("@", TRUE);
> 
> 
> This should already be available in XS as ERRSV.

Thanks Matt. I'm already using it.

I was wondering whether util.c's pod needs to be updated to use it too.

I see some segfault using my proposal with:
$SIG{__DIE__} = \&Carp::confess;
Still haven't figured out why.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com

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


Re: [mp2] a new exceptions handling proposal

Posted by Matt Sergeant <ma...@sergeant.org>.
On 29 Apr 2004, at 19:56, Stas Bekman wrote:

>     SV *errsv = get_sv("@", TRUE);

This should already be available in XS as ERRSV.

Matt.


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