Steve Hay wrote:

Closer still:

- perl t/TEST t/api/lookup_uri t/api/rflush t/apr/pool t/filter/both_str_con_add
fails


- perl t/TEST t/api/lookup_uri t/api/rflush t/filter/both_str_con_add
passes

- perl t/TEST t/api/lookup_uri t/apr/pool t/filter/both_str_con_add
fails

- perl t/TEST t/api/rflush t/apr/pool t/filter/both_str_con_add
passes

Concentrating on the shortest sequence that still fails (lookup_uri + pool + both_str_con_add), I find that the attached patch (which truncates the t/apr/pool tests from 13 to just 2) makes this test sequence succeed.

Most interestingly, if you move the "return Apache::OK;" that I've inserted into pool.pm down one more line, to just *after* the "$p->destroy();", then the test sequence fails again.

Perhaps there is a problem with APR::Pool->destroy()?

More tidbits that might help someone sort this out:


1. If I further hack pool.pm to remove all reference to $subp, i.e. delete these lines:

   my $subp = $p->new;
   ok $subp->isa('APR::Pool');
   $subp->cleanup_register(\&set_cleanup, [$r, 'child']);

(so now there is only 1 test left!) then it works *with* the $p->destroy() call left in. That call is commented "# should destroy the subpool too"; it seems that it destroys more than just the subpool ;-)

2. Having the ability to make the failing test sequence work allows me to compare what's going on in modperl_filter_new() in a run that fails with a run that works. Here's what I find:

On the failed run (with the destroy() call) I have these values before and after the apr_pcalloc() call:

VARIABLE BEFORE AFTER

f        0x008e23c8    unchanged
f->ctx        0x008e23b8    NULL
f->r        NULL        unchanged - still NULL
f->c        0x008e1db8    NULL
f->c->pool    0x008e1cb8    N/A since f->c is NULL

filter        0x01d175dc    0x008e1cb8 (*)
filter->f    0x34302e00    NULL
filter->pool    0x016e484c    NULL

p 0x008e1cb8 unchanged

The interesting thing there is marked (*): It seems that what apr_pcalloc() has returned (which gets assigned to filter) is the address held in p -- i.e. the address that was passed into it. I would (naively) expect apr_pcalloc() to have zeroed the memory at the address that it returns, and, indeed, everything "under" filter is NULL or 0. However, p came from f->c->pool, so zeroing that could potentially affect things "under" f, and sure enough f->ctx and f->c do get changed to NULL (causing the crash).

By contrast, on the successful run (without the destroy() call) I have this:

VARIABLE BEFORE AFTER

f        0x008e23c8    unchanged
f->ctx        0x008e23b8    unchanged
f->r        NULL        unchanged
f->c        0x008e1db8    unchanged
f->c->pool    0x008e1cb8    unchanged

filter        0x01f0f704    0x033692e8 (*)
filter->f    0x34302e00    NULL
filter->pool    0xffffffff    NULL

p 0x008e1cb8 unchanged

This time, the return value from apr_pcalloc(), assigned to filter, is an address that we haven't seen before. Again, everything "under" filter is NULL or 0, but this time nothing "under" f has been changed at all.

It looks like the problem is not so much that f->ctx et al gets zeroed, as that apr_pcalloc() returns something "under" f (namely, f->c->pool) as the zeroed memory, rather than a "new" area of memory. The fact that f->ctx et al gets zeroed is just a consequence of that.

Was it at all relevant that on the successful run filter->pool was 0xffffffff to start with? That value wouldn't normally just crop up by accident!

- Steve


--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]



Reply via email to