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?