Hi,
I am in the middle of the analysis of a segfault. The
segfault happens in a
$r->push_handlers(PerlFixupHandler=>sub{}).
Unfortunately it happens not for
every request but after 13. Finally, I think I have tracked
it down to
something to talk about.
The modperl_handler_lookup_handlers function looks this:
MpAV **modperl_handler_lookup_handlers(modperl_config_dir_t
*dcfg,
modperl_config_srv_t
*scfg,
modperl_config_req_t
*rcfg,
apr_pool_t *p,
int type, int idx,
modperl_handler_action_e action,
const char **desc)
{
MpAV **avp = NULL, **ravp = NULL;
[...]
case MP_HANDLER_ACTION_PUSH:
if (ravp && !*ravp) {
if (*avp) {
/* merge with existing configured handlers
*/
*ravp = apr_array_copy(p, *avp);
}
else {
/* no request handlers have been previously
pushed or set */
*ravp = modperl_handler_array_new(p);
}
}
else if (!*avp) {
/* directly modify the configuration at startup
time */
*avp = modperl_handler_array_new(p);
}
break;
It is called during said push_handlers. For the very first
request it takes
the "else if (!*avp)" route. This is I think wrong
because it modifies
dcfg->handlers_per_dir[idx] instead of
dcfg->handlers_per_dir[idx].
p in this case is a request pool. So after the request is
over the pool is
destroyed but dcfg still holds a pointer allocated from it
in dcfg.
12 requests later a completely different apr_palloc returns
the same pointer
and in my setup **avp is overwritten by a string.
So, how can it be that the "else if (!*avp)" route
is taken at request time
and how can it be avoided?
Thanks,
Torsten
|