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

Reply via email to