Mark James wrote:
Stas Bekman wrote:

Mark James wrote:

The cause of the problem was my perl code calling flush.pl and
flushing STDOUT at a point prior to it printing the response headers.


Hmm, why do you flush?


STDOUT is flushed prior to a fork to exec an external binary (rcs).
The child is closing STDOUT and then redirecting it into a pipe
to the parent.  I didn't write this part of the code, but the
comment on the flushing is:

# flush now, lest data in a buffer get flushed on close() in every stinking
# child process.


The code for the forking is:
    "bulletproof fork" from camel book, 2ed, page 167

If necessary I can propose a patch to this perl package to make the
flushing conditional on not running under mod_perl.

I understand the cause. But I hope that you agree with me that this is an application's problem. If you haven't sent anything to STDOUT yet, don't flush. And if this is not under your control, reopen STDOUT to /dev/null before you call that piece of code, that flushes and then re-tie STDOUT again.
(See t/response/TestModperl/request_rec_tie_api.pm)


Technically it's possible to add a flag in mod_perl 2.0 to ignore any flush attempts, if no data data was printed yet. However, this could become an undesirable behavior for someone who wants to send a flush before any data is sent. In your case, you can work around the problem, in the case of a person who wants the other behavior, there is no workaround. So I suggest that we keep the mp behavior generic and not create special cases we may regret about later on.

The way Apache2 is designed is that the moment you send anything down the filter chain, the headers are generated, because they have to be sent before any data goes out. However mod_perl has an internal buffer and it won't flush the data before it gets full or the code tells it to flush using $r->rflush. If $|==0, then the buffer is not used and the data is flushed on every print.


I see. But why is there no problem when using mod_cgi?

That's an interesting question. mod_cgi is a generic handler, which can run applications written in any language. Therefore it has no clue of what flush is. It simply creates a pipe to the application, and expects the headers headers followed by the data.


In your case, when cgi script flushes STDOUT, nothing happens at all, because there is no data to flush. So mod_cgi gets the headers and the data and all is cool.

When the same code is run under mod_perl, flush generates a special bucket which is sent out to the filters chain, and since no headers are generated yet, they get generated and sent out.

As I wrote this, I'm actually starting to think that it's Apache who should ignore the flush bucket if it had seen no other data so far, and not generate any headers till it actually sees the real data.

Everything seems to work if the ap_rflush call is removed
from mpxs_output_flush, but I don't know if this is the
proper way to fix it.



No, this is not a proper way to fix it. Otherwise those who want to flush their output won't be able to do so.


Why would a perl handler script want to flush data down the filter chain
before it had finished writing all of it?

Here is an example: You have a long running process, you want the headers to be sent immediately, but the data won't follow for a while. So you create the headers, do $r->rflush, and later on send the data.


__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:[EMAIL PROTECTED] http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com



Reply via email to