Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: ModPerl: ModPerl

Question about Apache2::ServerUtil and PerlCleanupHandler

 

 

ModPerl modperl RSS feed   Index | Next | Previous | View Threaded


kostas at chatzi

Dec 5, 2008, 5:25 AM

Post #1 of 4 (358 views)
Permalink
Question about Apache2::ServerUtil and PerlCleanupHandler

Hello,

I'd like to ask what is the intended behaviour of
Apache2::ServerUtil->server->push_handlers(PerlCleanupHandler => ...)
compared to
Apache2::RequestUtil->request->push_handlers(PerlCleanupHandler => ...)

On my Ubuntu 8.10 (mod_perl 2.0.4, apache 2.2.9) cleanup handlers
installed on $s seem to be called after *every* request but handlers
installed on $r are called only *once* after the *current* request. On a
RedHat ES 5 (mod_perl 2.0.2, apache 2.2.3) cleanup handlers on $s look
like they are never called.

I found and old list message suggesting that cleanup handlers on $s are
called when the server is terminated, but this doesn't seem to be the
case (and looks strange since we have PerlChildExitHandler for that). In
the documentation of handlers, there is no mention of where each handler
must be installed and whether it makes a difference.


NOTE: on my Ubuntu, a cleanup handler installed on $s is called only if
there are also other types of handlers on $s. In the Changelog of the
*threading branch* I found the following message

Now correctly invokes PerlCleanupHandlers, even if they are the only
handler type configured for that request [Torsten Foertsch]

this comes from r594609 but it was not merged for 2.0.4. This maybe
happens also for $r handlers, but on my setup $r has always at least a
PerlResponseHandler so I'm not sure.


Thanks in advance,
Kostas


aw at ice-sa

Dec 5, 2008, 6:35 AM

Post #2 of 4 (329 views)
Permalink
Re: Question about Apache2::ServerUtil and PerlCleanupHandler [In reply to]

Hi.

Without being an expert, this is my 2 cent :

Kostas Chatzikokolakis wrote:
> Hello,
>
> I'd like to ask what is the intended behaviour of
> Apache2::ServerUtil->server->push_handlers(PerlCleanupHandler => ...)
> compared to
> Apache2::RequestUtil->request->push_handlers(PerlCleanupHandler => ...)
>
> On my Ubuntu 8.10 (mod_perl 2.0.4, apache 2.2.9) cleanup handlers
> installed on $s seem to be called after *every* request but handlers
> installed on $r are called only *once* after the *current* request.

That sounds like the correct behaviour.

On a
> RedHat ES 5 (mod_perl 2.0.2, apache 2.2.3) cleanup handlers on $s look
> like they are never called.
>

That sounds like a bug, but..

[...]
>
> Now correctly invokes PerlCleanupHandlers, even if they are the only
> handler type configured for that request [Torsten Foertsch]
>
He's the real expert, I'm not.

Basically, the way I understand this is :
x->push_handlers(handlerType => ref)
means that you are *adding* a handler (which was not there before) to
"x", at a certain moment in time and under certain circumstances.
That handler will be there (and will be invoked), from the moment you
add it, and as long as "x" exists. When "x" ceases to exist, the
handler will also disappear.

$r (the request) exists only during the handling of this request. So any
handler you add to it will cease to exist after this request terminates,
and will thus have effect only on this request.

$s is "the server", which I interpret as being, in a prefork type
Apache, as one of the Apache children processes.
Initially, the Apache child starts, and your handler is not there (*).
Then, based on some event or condition, you do $s->push_handlers(), and
the handler is there. As long as this child is alive (which depends on
many factors), it will continue to be there, and be involved in any
request processed by this particular child.
But when this child terminates, it also disappears. If a new child is
started, whether your handler is again "pushed" onto it, depends on you.

Since you cannot really predict which child will handle the next
request, and for how many requests a child will remain alive, this might
give rise to the funny-looking behaviour you point out, unless you are
very sure that each time a new child is started, you always push your
handler onto it.

The above is my understanding, and for the prefork-type, where each
child is a process. I am a lot less sure of what happens under a
threaded model.

Also, all of the above is based on the fact that you do a
push_handler(), not systematically, but presumably in function of
certain conditions. ((*)Because otherwise why not just put it into your
basic configuration, and have it be there all the time ?).
I can understand easily why one does that within a request.
But I have more trouble understanding why one would use this at the
server level. It means that, depending on some condition, when a new
child starts, you would or would not add a given handler to it.
What would be such a condition that would make sense ?


torsten.foertsch at gmx

Dec 5, 2008, 6:50 AM

Post #3 of 4 (328 views)
Permalink
Re: Question about Apache2::ServerUtil and PerlCleanupHandler [In reply to]

On Fri 05 Dec 2008, Kostas Chatzikokolakis wrote:
> I'd like to ask what is the intended behaviour of
>  Apache2::ServerUtil->server->push_handlers(PerlCleanupHandler =>
> ...) compared to
>  Apache2::RequestUtil->request->push_handlers(PerlCleanupHandler =>
> ...)
>
> On my Ubuntu 8.10 (mod_perl 2.0.4, apache 2.2.9) cleanup handlers
> installed on $s seem to be called after *every* request but handlers
> installed on $r are called only *once* after the *current* request.
> On a RedHat ES 5 (mod_perl 2.0.2, apache 2.2.3) cleanup handlers on
> $s look like they are never called.
>
> I found and old list message suggesting that cleanup handlers on $s
> are called when the server is terminated, but this doesn't seem to be
> the case (and looks strange since we have PerlChildExitHandler for
> that). In the documentation of handlers, there is no mention of where
> each handler must be installed and whether it makes a difference.
>
>
> NOTE: on my Ubuntu, a cleanup handler installed on $s is called only
> if there are also other types of handlers on $s. In the Changelog of
> the *threading branch* I found the following message
>
>   Now correctly invokes PerlCleanupHandlers, even if they are the
> only handler type configured for that request [Torsten Foertsch]
>
> this comes from r594609 but it was not merged for 2.0.4. This maybe
> happens also for $r handlers, but on my setup $r has always at least
> a PerlResponseHandler so I'm not sure.

Apache request configuration is performed in 2 steps. The first occurs
at startup the second at runtime. At startup one configuration object
per virtual server is created. At runtime a request inherits from that
config but other request specific configuration sources (Location
blocks, .htaccess files etc) are merged.

$s->push_handlers as well as $s->add_config modify the server
configuration object while $r->... modify the runtime request
configuration. The server methods are intended to be used only at
startup time (up to PerlPostConfig, perhaps PerlChildInit works too).
Later the server configuration must be read-only or you risk segfaults
at least on a threaded MPM.

The PerlCleanup phase is an artificial thing that is implemented as a
pool cleanup function on the request pool. But it needs to be
registered on the request pool to be run. If there is no Perl handler
in the request cycle the pool cleanup is never installed. The patch you
mentioned fixes that but it depends on an other interpreter management
(the heart of the threading branch). Hence, if you need that use the
threading branch. I use it for quite a time now in production with
prefork. I know there are issues with worker. So, I don't recommend
that.

In modperl_callback.c at line 202 you'll find these lines:

/* XXX: would like to do this in modperl_hook_create_request()
* but modperl_interp_select() is what figures out if
* PerlInterpScope eq handler, in which case we do not register
* a cleanup. modperl_hook_create_request() is also currently always
* run even if modperl isn't handling any part of the request
*/
modperl_config_req_cleanup_register(r, rcfg);

This is inside the modperl_callback_run_handlers() function which is the
central point that runs all PerlXXXHandlers. That's why you need at
least one PerlXXXHandler to activate the PerlCleanupHandler. In the
threading branch the modperl_config_req_cleanup_register() call could
have been moved to the create_request hook as mentioned in the comment.

Torsten

--
Need professional mod_perl support?
Just hire me: torsten.foertsch[at]gmx.net


kostas at chatzi

Dec 5, 2008, 9:44 AM

Post #4 of 4 (330 views)
Permalink
Re: Question about Apache2::ServerUtil and PerlCleanupHandler [In reply to]

Thanks for the quick and prompt reply guys.

> $s->push_handlers as well as $s->add_config modify the server
> configuration object while $r->... modify the runtime request
> configuration. The server methods are intended to be used only at
> startup time (up to PerlPostConfig, perhaps PerlChildInit works too).
> Later the server configuration must be read-only or you risk
> segfaults at least on a threaded MPM.

This clarifies things. Indeed, using $s->push_handlers at PerlPostConfig
I get consistent behaviour and the cleanup handler is always executed
(even on RH 5). Using $s->push_handlers at a later stage has weird
behaviour.

> The PerlCleanup phase is an artificial thing that is implemented as a
> pool cleanup function on the request pool. But it needs to be
> registered on the request pool to be run. If there is no Perl handler
> in the request cycle the pool cleanup is never installed.

I see. Note that in my tests, a cleanup handler installed on $s is only
executed if another handler is installed *also on $s*. I have a
PerlResponseHandler installed through httpd.conf, then if I install a
cleanup on $r it runs, but on $s it does not. If I add another handler
on $s (eg a PerlPostReadRequestHandler) then cleanup on $s also run.

This does not really affect me (I'll stick to $r anyway), I just thought
to mention it in case it also needs to be fixed.



> Also, all of the above is based on the fact that you do a
> push_handler(), not systematically, but presumably in function of
> certain conditions. ((*)Because otherwise why not just put it into
> your basic configuration, and have it be there all the time ?). I can
> understand easily why one does that within a request. But I have more
> trouble understanding why one would use this at the server level. It
> means that, depending on some condition, when a new child starts, you
> would or would not add a given handler to it. What would be such a
> condition that would make sense ? From - Fri

I was trying to debug code that uses $s->push_handlers (which I didn't
know what it does) and it looks like it should be using $r. Indeed I
think that $s->push_handlers is for rare cases.


Kostas

ModPerl modperl RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact lists@gossamer-threads.com
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.