You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@perl.apache.org by Torsten Foertsch <to...@gmx.net> on 2007/05/03 13:32:45 UTC
[PATCH]Re: threaded server + scope=handler: modperl_response_handler vs. modperl_response_handler_cgi
On Monday 30 April 2007 12:08, Torsten Foertsch wrote:
> This means in both cases modperl_interp_select is called twice but for the
> perl-script case rcfg->interp = interp is set.
>
> modperl_interp_select first looks if rcfg->interp is set and returns it.
> Only if it's not it looks at other places for an interpreter.
>
> This means a perl-script handler needs 1 interpreter to handle the response
> phase while a modperl handler needs 2.
On Tuesday 01 May 2007 12:24, Torsten Foertsch wrote:
> On Monday 30 April 2007 22:22, Philippe M. Chiasson wrote:
> > And that doesn't seem logical at all. In all cases, since the initial
> > int= erpreter
> > is tied up in modperl_response_handler() a new one shouldn't be needed
> > to= dispatch
> > that handler part.
>
> I have found similar bug. Try
>
> $r->push_handlers(PerlCleanupHandler=>'some_named_function')
>
> from a TranslationHandler or so.
[...]
> Or maybe a cleaner way is to use interp->refcnt. Simply increment it each
> time modperl_interp_select returns it. For what I can see refcnt isn't used
> at all by now. Yes, on a second thought that is what I'd prefer.
The attached patch fixes these 2 issues. It is against r534739. I have tested
it with prefork and worker with a httpd 2.2.3 on linux.
What does it change?
1) it moves the handling of rcfg->interp from modperl_response_handler and
modperl_response_handler_cgi to modperl_interp_select /
modperl_interp_unselect.
2) If interp is saved to rcfg it counts as a reference to it. So refcnt is
incremented.
All other changes are MP_TRACE macros to see what is going on.
Now the program flow is this:
If scope==request, connection or subrequest the PUTBACK flag is allways off.
Interp is stored in the pool and modperl_interp_unselect is called by pool
cleanup. Nothing has changed.
If scope==handler PUTBACK is on. Interp is not stored in a pool but allways in
rcfg. So recursive calls to modperl_interp_select will find it there and
increment its refcnt. Hence an equal number of calls to
modperl_interp_unselect is required to really release the interp.
So, both modperl_response_handler allocate an interpreter then call
modperl_callback_run_handlers which recursively allocates the same interp
found in rcfg. The putback operation in modperl_callback_run_handlers then
only decrements the refcnt and the putback in modperl_response_handler really
does the unselect. But unselect has to call PerlCleanupHandlers. So
modperl_interp_select is called again (while in modperl_interp_unselect),
finds the interp in rcfg and increments its refcnt. After all cleanup
handlers are run modperl_callback_run_handlers calls unselect which simply
decrements the refcnt. Then modperl_config_request_cleanup returns to the
outer modperl_interp_unselect and the interp is really freed.
Cleanup handlers installed via PerlCleanupHandler are thus called each time an
interp is really freed.
$r->pool cleanups behave different. A pool cleanup_register also increments an
interp's refcnt. Now if a pool cleanup is installed say in the translation
phase the interp has allways a refcnt>0. So it is not released until the pool
is destroyed. And since interp is stored in rcfg it is sticky to the request.
All other phases after the pool cleanup installation will be handled by the
same interp.
Torsten