Re: mod_perl memory

Torsten Förtsch <[email protected]>
Newsgroups gmane.comp.apache.mod-perl
Message-ID <[email protected]>
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.