Question about Apache2::ServerUtil and PerlCleanupHandler

Question about Apache2::ServerUtil and PerlCleanupHandler

am 05.12.2008 14:25:04 von Kostas Chatzikokolakis

Hello,

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

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

Re: Question about Apache2::ServerUtil and PerlCleanupHandler

am 05.12.2008 15:35:57 von aw

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(PerlCleanupHandle r => ...)
> compared to
> Apache2::RequestUtil->request->push_handlers(PerlCleanupHand ler => ...)
>
> 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 ?

Re: Question about Apache2::ServerUtil and PerlCleanupHandler

am 05.12.2008 15:50:35 von torsten.foertsch

On Fri 05 Dec 2008, Kostas Chatzikokolakis wrote:
> I'd like to ask what is the intended behaviour of
> =A0Apache2::ServerUtil->server->push_handlers(PerlCleanupHan dler =3D>
> ...) compared to
> =A0Apache2::RequestUtil->request->push_handlers(PerlCleanupH andler =3D>
> ...)
>
> 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
>
> =A0 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=20
at startup the second at runtime. At startup one configuration object=20
per virtual server is created. At runtime a request inherits from that=20
config but other request specific configuration sources (Location=20
blocks, .htaccess files etc) are merged.

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

The PerlCleanup phase is an artificial thing that is implemented as a=20
pool cleanup function on the request pool. But it needs to be=20
registered on the request pool to be run. If there is no Perl handler=20
in the request cycle the pool cleanup is never installed. The patch you=20
mentioned fixes that but it depends on an other interpreter management=20
(the heart of the threading branch). Hence, if you need that use the=20
threading branch. I use it for quite a time now in production with=20
prefork. I know there are issues with worker. So, I don't recommend=20
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=20
central point that runs all PerlXXXHandlers. That's why you need at=20
least one PerlXXXHandler to activate the PerlCleanupHandler. In the=20
threading branch the modperl_config_req_cleanup_register() call could=20
have been moved to the create_request hook as mentioned in the comment.

Torsten

=2D-=20
Need professional mod_perl support?
Just hire me: torsten.foertsch@gmx.net

Re: Question about Apache2::ServerUtil and PerlCleanupHandler

am 05.12.2008 18:44:09 von Kostas Chatzikokolakis

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