On Mar 17, 2010, at 11:27 AM, Torsten Förtsch wrote:
> On Wednesday 17 March 2010 12:15:15 Torsten Förtsch wrote:
>> On Tuesday 16 March 2010 21:09:33 Pavel Georgiev wrote:
>>> for (<some condition>) {
>>> $request->print("--$this->{boundary}\n");
>>> $request->print("Content-type: text/html; charset=utf-8;\n\n");
>>> $request->print("$data\n\n");
>>> $request->rflush;
>>> }
>>>
>>> And the result is endless memory growth in the apache process. Is that
>>> what you had in mind?
>>>
>>
>> I can confirm this. I have tried this little handler:
>>
>> sub {
>> my $r=shift;
>>
>> until( -e "/tmp/stop" ) {
>> $r->print(("x"x70)."\n");
>> $r->rflush;
>> }
>>
>> return Apache2::Const::OK;
>> }
>>
>> The httpd process grows slowly but unlimited. Without the rflush() it
>> grows slower but still does.
>>
> Here is a bit more stuff on the bug. It is the pool that grows.
>
> To show it I use a handler that prints an empty document. I think an empty
> file shipped by the default handler will do as well.
>
> Then I add the following filter to the request:
>
> $r->add_output_filter(sub {
> my ($f, $bb)=...@_;
>
> unless( $f->ctx ) {
> $f->r->headers_out->unset('Content-Length');
> $f->ctx(1);
> }
>
> my $eos=0;
> while( my $b=$bb->first ) {
> $eos++ if( $b->is_eos );
> $b->delete;
> }
> return 0 unless $eos;
>
> my $ba=$f->c->bucket_alloc;
> until( -e '/tmp/stop' ) {
> my $bb2=APR::Brigade->new($f->c->pool, $ba);
> $bb2->insert_tail(APR::Bucket->new($ba, ("x"x70)."\n"));
> $bb2->insert_tail(APR::Bucket::flush_create $ba);
> $f->next->pass_brigade($bb2);
> }
>
> my $bb2=APR::Brigade->new($f->c->pool, $ba);
> $bb2->insert_tail(APR::Bucket::eos_create $ba);
> $f->next->pass_brigade($bb2);
>
> return 0;
> });
>
> The filter drops the empty document and emulates our infinite output. With
> this filter the httpd process still grows. Now I add a subpool to the loop:
>
> [...]
> until( -e '/tmp/stop' ) {
> my $pool=$f->c->pool->new; # create a subpool
> my $bb2=APR::Brigade->new($pool, $ba); # use the subpool
> $bb2->insert_tail(APR::Bucket->new($ba, ("x"x70)."\n"));
> $bb2->insert_tail(APR::Bucket::flush_create $ba);
> $f->next->pass_brigade($bb2);
> $pool->destroy; # and destroy it
> }
> [...]
>
> Now it does not grow.
>
> Torsten Förtsch
>
> --
> Need professional modperl support? Hire me! (http://foertsch.name)
>
> Like fantasy? http://kabatinte.net
How would that logic (adding subpools and using them) be applied to my
simplified example:
for (;;) {
$request->print("--$this->{boundary}\n");
$request->print("Content-type: text/html; charset=utf-8;\n\n");
$request->print("$data\n\n");
$request->rflush;
}
Do I need to add an output filter?