Re: return from nested functions
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
Re: return from nested functions
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
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). > or die SERVER_ERROR; But that works. Thanks! :) - Paul
Re: return from nested functions
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
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
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}; > } > ; > } 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
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
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
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}; } ; } 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). -- /||** 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
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
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
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
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
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 ==*/