Re: return from nested functions

2000-11-01 Thread Dave Rolsky

On Wed, 1 Nov 2000, Paul J. Lucas wrote:

   If I'm a few levels deep into function calls, I'd liek to be
   able to do something like "return SERVER_ERROR" and have the
   entire call stack unwind and the current request stopped.
 
   Is there any way to do that?

Not that this has anything to do with mod_perl really but ...

Use exceptions.  There's a section in the guide on them some crazy guy
wrote ;)

I recommend my Exception::Class module on CPAN.  But I would do that,
wouldn't I?


-dave

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




Re: return from nested functions

2000-11-01 Thread Ben Cottrell

On Wed, 1 Nov 2000 11:37:00 -0800 (PST), "Paul J. Lucas" wrote:
   If I'm a few levels deep into function calls, I'd liek to be
   able to do something like "return SERVER_ERROR" and have the
   entire call stack unwind and the current request stopped.

Will something like this do what you need?

~Ben



eval
{
get as many levels deep into functions as you want
...
...
...
die("SERVER_ERROR");
...
...
...
};

$the_error = $@;
if ($the_error)
{
warn("Unwound stack because of $the_error");
}



Re: return from nested functions

2000-11-01 Thread G.W. Haywood

Hi there,

On Wed, 1 Nov 2000, Paul J. Lucas wrote:

   If I'm a few levels deep into function calls, I'd liek to be
   able to do something like "return SERVER_ERROR" and have the
   entire call stack unwind and the current request stopped.
 
   Is there any way to do that?

It's called a 'goto' (and real programmers don't use it:).

Or you could call a function which does the business and then calls
mod_perl's exit() function, page 464 Eagle Book.

Don't use an ordinary exit() from a mod_perl process because that
abruptly kills the child, which is Bad News.

73,
Ged.





Re: return from nested functions

2000-11-01 Thread Paul J. Lucas

On Wed, 1 Nov 2000, G.W. Haywood wrote:

 Or you could call a function which does the business and then calls
 mod_perl's exit() function, page 464 Eagle Book.

I tried exit: the status code isn't preserved to downstream
stacked handlers.

- Paul




Re: return from nested functions

2000-11-01 Thread Paul J. Lucas

On Wed, 1 Nov 2000, Dave Rolsky wrote:

 On Wed, 1 Nov 2000, Paul J. Lucas wrote:
 
  If I'm a few levels deep into function calls, I'd liek to be
  able to do something like "return SERVER_ERROR" and have the
  entire call stack unwind and the current request stopped.
  
  Is there any way to do that?
 
 Not that this has anything to do with mod_perl really but ...

Actually it does because the status code should be preserved to
downstream stacked handlers (and, my testing, it apparantly
isn't):

sub some_nested_function {
$r-status( SERVER_ERROR );
Apache-exit( 0 );
}

# in downstream.pm handler
sub handler {
# $r-status() is NOT SERVER_ERROR here
}

- Paul




Re: return from nested functions

2000-11-01 Thread Matt Sergeant

On Wed, 1 Nov 2000, Paul J. Lucas wrote:

   If I'm a few levels deep into function calls, I'd liek to be
   able to do something like "return SERVER_ERROR" and have the
   entire call stack unwind and the current request stopped.
 
   Is there any way to do that?

Definitely use exceptions. I prefer Error.pm for this (sorry, Dave!),
which allows your handler to simply be:

sub handler {
return try {
...
} catch Exception::RetCode with {
my $E = shift;
return $E-{code};
} other exceptions
;
}

And then anywhere within your code you can go:

throw Exception::RetCode ( code = SERVER_ERROR );

Of course there's a bit of setup to do beyond that, which I intend to
rewrite the section of the guide to detail real soon now (tm).

-- 
Matt/

/||** Director and CTO **
   //||**  AxKit.com Ltd   **  ** XML Application Serving **
  // ||** http://axkit.org **  ** XSLT, XPathScript, XSP  **
 // \\| // ** Personal Web Site: http://sergeant.org/ **
 \\//
 //\\
//  \\




Re: return from nested functions

2000-11-01 Thread Dave Rolsky

On Wed, 1 Nov 2000, Matt Sergeant wrote:

 Definitely use exceptions. I prefer Error.pm for this (sorry, Dave!),
 which allows your handler to simply be:

That's no reason not to use Exception::Class.  They are largely
orthogonal.  If you want to be able to declare your exception hierarchy at
compile time and have it enforced (this is a good thing!) then check out
Exception::Class.

If you want Try/Catch syntax get Error.pm.

Both of them come with Exception object implementations.  I don't know
about Error but with Exception::Class you don't have to use it (you could
even use Error's, I think).


-dave

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




Re: return from nested functions

2000-11-01 Thread Paul J. Lucas

On Wed, 1 Nov 2000, Matt Sergeant wrote:

 On Wed, 1 Nov 2000, Paul J. Lucas wrote:
 
  If I'm a few levels deep into function calls, I'd liek to be
  able to do something like "return SERVER_ERROR" and have the
  entire call stack unwind and the current request stopped.
  
  Is there any way to do that?
 
 Definitely use exceptions.

It's rather cumbersome.  Ideally, I want to be able to do:

sub foo {
if ( $serious_problem )
stop_now_dammit( SERVER_ERROR );
}

anywhere in the code like:

sub bar {
foo();
}

and I do *NOT* have to "catch" anything after the point of
call, i.e., every call of foo() is similar to an "assertion" in
C, i.e., if you get to the line of code after it, it worked; if
it didn't work, you never get to the line after it.

I suppose I want to do something like Apache-exit() but
preserve the response code so the normal Apache error handling
mechanism kicks in and handles the error.

- Paul




Re: return from nested functions

2000-11-01 Thread Perrin Harkins

On Wed, 1 Nov 2000, Matt Sergeant wrote:
 Definitely use exceptions. I prefer Error.pm for this (sorry, Dave!),
 which allows your handler to simply be:
 
 sub handler {
   return try {
   ...
   } catch Exception::RetCode with {
   my $E = shift;
   return $E-{code};
   } other exceptions
   ;
 }

Be very careful with nested try/catch blocks.  Error.pm uses prototypes to
make these into anonymous subs, which is usually fine, but this leaks
memory like mad:

my $foo;
try {
something();
try {
$foo++;
};
} otherwise {
handle_error();
};

It's not Graham Barr's fault; that's just a byproduct of Perl's support
for closures (I think).

- Perrin




Re: return from nested functions

2000-11-01 Thread Paul J. Lucas

On Wed, 1 Nov 2000, Paul J. Lucas wrote:

   Ideally, I want to be able to do:
 
   sub foo {
   if ( $serious_problem )
   stop_now_dammit( SERVER_ERROR );
   }
 
   anywhere in the code like:
 
   sub bar {
   foo();
   }
 
   and I do *NOT* have to "catch" anything after the point of
   call, i.e., every call of foo() is similar to an "assertion" in
   C, i.e., if you get to the line of code after it, it worked; if
   it didn't work, you never get to the line after it.

I figured out that I can do this by having stop_now_dammit()
use $r-notes() to set a note of the status code, call
Apache-exit(), and have the downstream handler check the note.
If it's anything but OK, simply return that value and the
normal Apache error handline mechanism kicks in.  :)

- Paul




Re: return from nested functions

2000-11-01 Thread John K. Sterling


even better: Apache-exit(SERVER_ERROR);.  or die SERVER_ERROR;. this is
documented in the eagle book:

ch9 -  The Apache::Constants Class

"...
While the HTTP constants are generally used as return codes from
handler subroutines, it is also possible to use the builtin die()
function to jump out of a handler with a status code that will be
propagated back to Apache.  Example:

 unless (-r _) {
 die FORBIDDEN;
 }
"
sterling


On Wed, 1 Nov 2000, Paul J. Lucas wrote:

 On Wed, 1 Nov 2000, Paul J. Lucas wrote:
 
  Ideally, I want to be able to do:
  
  sub foo {
  if ( $serious_problem )
  stop_now_dammit( SERVER_ERROR );
  }
  
  anywhere in the code like:
  
  sub bar {
  foo();
  }
  
  and I do *NOT* have to "catch" anything after the point of
  call, i.e., every call of foo() is similar to an "assertion" in
  C, i.e., if you get to the line of code after it, it worked; if
  it didn't work, you never get to the line after it.
 
   I figured out that I can do this by having stop_now_dammit()
   use $r-notes() to set a note of the status code, call
   Apache-exit(), and have the downstream handler check the note.
   If it's anything but OK, simply return that value and the
   normal Apache error handline mechanism kicks in.  :)
 
   - Paul
 




Re: return from nested functions

2000-11-01 Thread John K. Sterling

On Wed, 1 Nov 2000, Paul J. Lucas wrote:

 On Wed, 1 Nov 2000, John K. Sterling wrote:
 
  even better: Apache-exit(SERVER_ERROR);
 
   The documentation for exit() deosnt' explicitly say you can do
   that.  It mentions only "0" and "DONE" (see pp. 464-465).


it works though, Apache.xs:exit() passes the status value to
perl_util.c:perl_call_halt(), which checks:
int is_http_code = 
((status = 100)  (status  600)  ERRSV_CAN_BE_HTTP);

...

if(is_http_code) {
croak("%d\n", status);
}

the croak() call is caught the same way 'die SERVER_ERROR' is.



 
  or die SERVER_ERROR;
 
   But that works.  Thanks!  :)
 
   - Paul
 




Re: return from nested functions

2000-11-01 Thread Craig McLane

On Wed, 1 Nov 2000, Dave Rolsky wrote:

 On Wed, 1 Nov 2000, Paul J. Lucas wrote:
 
  If I'm a few levels deep into function calls, I'd liek to be
  able to do something like "return SERVER_ERROR" and have the
  entire call stack unwind and the current request stopped.
  
  Is there any way to do that?
 
 Not that this has anything to do with mod_perl really but ...
 
 Use exceptions.  There's a section in the guide on them some crazy guy
 wrote ;)
 
 I recommend my Exception::Class module on CPAN.  But I would do that,
 wouldn't I?

I'll second that recommendation, at citysearch we are using
Exception::Class very successfully.  We are able to trap all sorts of
errors and the overhead is fairly small.

Craig