stas 2004/05/07 18:26:40
Modified: src/docs/2.0/api/APR Error.pod
Log:
explain the new exceptions mechanism
Revision Changes Path
1.2 +111 -8 modperl-docs/src/docs/2.0/api/APR/Error.pod
Index: Error.pod
===================================================================
RCS file: /home/cvs/modperl-docs/src/docs/2.0/api/APR/Error.pod,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -u -r1.1 -r1.2
--- Error.pod 7 May 2004 21:38:48 -0000 1.1
+++ Error.pod 8 May 2004 01:26:40 -0000 1.2
@@ -1,26 +1,129 @@
=head1 NAME
-APR::Error - Perl API for APR/mod_perl exceptions
+APR::Error - Perl API for APR/Apache/mod_perl exceptions
=head1 Synopsis
- use APR::Error ();
-
-
-
-
+ eval { $obj->mp_method() };
+ if ($@ && $ref $@ eq 'APR::Error' && $@ == $some_code) {
+ # handle the exception
+ }
+ else {
+ die $@; # rethrow it
+ }
=head1 Description
-C<APR::Error> provides ...
-
+Apache and APR API return status code for almost all methods, so if
+you didn't check the return code and handled any possible problems,
+you may have silent failures which may cause all kind of obscure
+problems. On the other hand checking the status code after each call
+is just too much of a kludge and makes quick prototyping/development
+almost impossible, not talking about the code readability. Having
+methods return status codes, also complicates the API if you need to
+return other values.
+
+Therefore to keep things nice and make the API readable we decided to
+not return status codes, but instead throw exceptions with
+C<APR::Error> objects for each method that fails. If you don't catch
+those exceptions, everything works transparently - perl will intercept
+the exception object and C<die()> with a proper error message. So you
+get all the errors logged without doing any work.
+
+Now, in certain cases you don't want to just die, but instead the
+error needs to be trapped and handled. For example if some IO
+operation times out, may be it is OK to trap that and try again. If we
+were to die with an error message, you would have had to match the
+error message, which is ugly, inefficient and may not work at all if
+locale error strings are involved. Therefore you need to be able to
+get the original status code that Apache or APR has generated. And the
+exception objects give you that if you want to. Moreover the objects
+contain additional information, such as the function name (in case you
+were eval'ing several commands in one block), file and line number
+where that function was invoked from. More attributes could be added
+in the future.
+
+C<APR::Error> uses method overloading, such that in boolean and
+numerical contexts, the object returns the status code; in the string
+context the full error message is returned.
+
+When intercepting exceptions you need to check whether C<$@> is an
+object (reference). If your application uses other exception objects
+you additionally need to check whether this is a an C<APR::Error>
+object. Therefore most of the time this is enough:
+
+ eval { $obj->mp_method() };
+ if ($@ && $ref $@ && $@ == $some_code)
+ warn "handled exception: $@";
+ }
+
+But with other, non-mod_perl, exception objects you need to do:
+
+ eval { $obj->mp_method() };
+ if ($@ && $ref $@ eq 'APR::Error' && $@ == $some_code)
+ warn "handled exception: $@";
+ }
+
+In theory you could even do:
+
+ eval { $obj->mp_method() };
+ if ($@ && $@ == $some_code)
+ warn "handled exception: $@";
+ }
+
+but it's possible that the method will die with a plain string and not
+an object, in which case C<$@ == $some_code> won't quite
+work. Remember that mod_perl throws exception objects only when Apache
+and APR fail, and in a few other special cases of its own (like
+C<L<exit|docs::2.0::api::ModPerl::Util/C_exit_>>).
+
+ warn "handled exception: $@" if $@ && $ref $@;
+
+For example you wrote a code that performs L<a socket
+read|docs::2.0::api::APR::Socket/C_recv_>:
+
+ my $buff = $sock->recv(1024);
+ my $rlen = length $buff;
+ warn "read $rlen bytes\n";
+
+and in certain cases it times out. The code will die and log the
+reason for the failure, which is fine, but later on you decide that
+you want to give the read another chance before dying. In which case
+you rewrite the code to handle the exception like so:
+
+ use APR::Const -compile => qw(TIMEUP);
+ my $buff = eval { $sock->recv(1024) };
+ if ($@) {
+ die $@ unless ref $@ && $@ == APR::TIMEUP;
+ goto retry;
+ }
+ my $rlen = length $buff;
+ warn "read $rlen bytes\n";
+
+Notice that we handle non-object and non-C<APR::Error> exceptions as
+well, by simply rethrowing them.
+
+
+Finally, the class is called C<APR::Error> because it needs to be used
+outside mod_perl as well, when called from
+C<L<APR|docs::2.0::api::APR>> applications written in perl.
+
+
+=head1 API
+
+=head2 C<cluck>
+C<cluck> is an equivalent of C<Carp::cluck> that works with
+C<APR::Error> exception objects.
+=head2 C<confess>
+C<confess> is an equivalent of C<Carp::confess> that works with
+C<APR::Error> exception objects.
=head1 See Also
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]