httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ian Holsman <i...@cnet.com>
Subject Re: cvs commit: httpd-2.0 STATUS
Date Mon, 02 Jul 2001 19:13:57 GMT
On 02 Jul 2001 15:02:20 -0400, Bill Stoddard wrote:
> 
> > On Mon, 2 Jul 2001, Bill Stoddard wrote:
> >
> > > >
> > > > >cgi on all platforms is broken.  Specifically, with the addition of
> > > > >filters, we have lost the ability to flush partially written buffers
> > > > >received from CGI scripts to the network.
> > > > [...]
> > > > >Apache 2.0 always does a blocking read (in the content length filter)
> > > >
> > > > Partial writes to the network from a CGI and content length are
> > > > mutually exclusive.
> > > >
> > >
> > > No S**t!! :-) That's why it's broken!
> > >
> > > Working on a fix now.
> >
> >
> > Bill, there is no fix for this.  If the content_length filter determines
> > that a C-L is required, then we can't stream CGI's.  It looks like the
> > problem is simply that we are using the wrong options to apr_bucket_read.
> > Switch that to a APR_NONBLOCK_READ, and the problem should go away.
> >
> > Ryan
> 
> I don't think changing the read in the content_length filter to nonblocking is the right
> solution to this problem because we still need to force the network flush. I will
> investigate your suggestion though because I might be overlooking something.
> 
> IMO the decision to flush or not and how to read from the pipe should be entirely
> controlled by mod_cgi.  We need a function similar to the old ap_send_fb() code.
> 
> To demonstrate, here is some code.   YES YES YES I know we don't want to commit this
as
> written. This code will cause a data copies of all bytes off the stack buffer and into
a
> heap buffer. Making this zero copy is easy enough, just wanted to post what I have been
> playing with the last 30 minutes to generally show how I think we should solve this
> problem (ie, control the byte stream at the top of the filter chain rather than deep
in
> the filter chain).
> 
> I also want to play with making the interface between Apache and CGI scripts full duplex
> as well (to allow a CGI script to read a large POST request and begin responding to that
> POST immediately) which will require controlling the byte stream at the top of the filter
> stack as well.
> 
> Bill

Hi Bill,
I was wondering if there was a generic way of doing this in a generic
fashion so that ALL dynamic content modules (perl/jk/proxy etc) 
would be affected (maybe putting it into the socket/pipe bucket read
functions)

..Ian
> 
> Index: mod_cgi.c
> ===================================================================
> RCS file: /home/cvs/httpd-2.0/modules/generators/mod_cgi.c,v
> retrieving revision 1.92
> diff -u -u -r1.92 mod_cgi.c
> --- mod_cgi.c 2001/02/28 15:24:05 1.92
> +++ mod_cgi.c 2001/07/02 18:26:53
> @@ -768,16 +768,43 @@
>   }
> 
>   if (!r->header_only) {
> +            #define IOBUFSIZE 8192
> +            apr_status_t rv;
> +            char buf[IOBUFSIZE];
> +            int len = IOBUFSIZE;
> +            apr_interval_time_t timeout;
> +
>              bb = apr_brigade_create(r->pool);
> -     b = apr_bucket_pipe_create(script_in);
> -     APR_BRIGADE_INSERT_TAIL(bb, b);
> -            b = apr_bucket_eos_create();
> -     APR_BRIGADE_INSERT_TAIL(bb, b);
> -     ap_pass_brigade(r->output_filters, bb);
> - }
> +
> +            /* Set the pipe to non-blocking for the first read */
> +            apr_file_pipe_timeout_get(script_in, &timeout);
> +            apr_file_pipe_timeout_set(script_in, 0);
> 
> -        log_script_err(r, script_err);
> - apr_file_close(script_err);
> +            while (!r->connection->aborted) {
> +                len = IOBUFSIZE;
> +                rv = apr_file_read(script_in, buf, &len);
> +                if (rv == APR_EOF || (rv == APR_SUCCESS && len == 0)) {
> +                    b = apr_bucket_eos_create();
> +                    APR_BRIGADE_INSERT_TAIL(bb, b);
> +                    ap_pass_brigade(r->output_filters, bb);
> +                    break;
> +                }
> +                else if (rv == APR_EAGAIN) {
> +                    /* Set the pipe to blocking and flush the output stream. */
> +                    apr_file_pipe_timeout_set(script_in, timeout);
> +                    b = apr_bucket_flush_create();
> +                    APR_BRIGADE_INSERT_TAIL(bb, b);
> +                    ap_pass_brigade(r->output_filters, bb);
> +                }
> +                else {
> +                    b = apr_bucket_transient_create(buf, len);
> +                    APR_BRIGADE_INSERT_TAIL(bb, b);
> +                    ap_pass_brigade(r->output_filters, bb);
> +                }
> +            }
> +            log_script_err(r, script_err);
> +            apr_file_close(script_err);
> +        }
>      }
> 
>      if (script_in && nph) {
> 



Mime
View raw message