apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Brad Nicholes" <BNICHO...@novell.com>
Subject Re: cvs commit: apr-util/buckets apr_buckets_pipe.c apr_buckets_socket.c
Date Tue, 16 Jul 2002 14:50:45 GMT
   The problem with the MOD_CGI case is that it *doesn't* call
pipe_bucket_read() with APR_BLOCK_READ.  In fact it calls it with
APR_NONBLOCK_READ which is what prompted the modification in the first
place.  If your analysis as to the definitions of APR_BLOCK_READ vs
APR_NONBLOCK_READ is correct, then let me dig a little deeper in the
code to figure out exactly why MOD_CGI is ultimately passing an
APR_NONBLOCK_READ (unless somebody else already knows).  What I do know
is that if pipe_socket_read() is allowed to return with an EWOULDBLOCK
error code, I end up with a browser response of "Premature end of
script..."  when in fact the data is there, just not at the right time.


Brad Nicholes
Senior Software Engineer
Novell, Inc., the leading provider of Net business solutions

>>> Justin Erenkrantz <jerenkrantz@apache.org> Tuesday, July 16, 2002
12:24:24 AM >>>
On Tue, Jul 16, 2002 at 05:50:40AM -0000, jerenkrantz@apache.org
> jerenkrantz    2002/07/15 22:50:40
>   Modified:    buckets  apr_buckets_pipe.c apr_buckets_socket.c
>   Log:
>   Revert rev 1.42 of apr_buckets_socket.c and rev 1.52 of
>   APR_NONBLOCK_READ means that we have no timeout - i.e. that we
>   immediately.  Leaving the timeout set by the 'upstream' application
>   incorrect in this state.
>   This fixes httpd-2.0 blocking in check_pipeline_flush() for EATCRLF

Brad's original commit had no chance of ever working as it made
APR_NONBLOCK_READ block.  There was discussion before about this
(and Cliff was right, IMHO), but the key concept missed was that
APR_NONBLOCK_READ means an immediate read, not a timeout-based read.

Let's sum up the APR socket timeouts and how they correspond to the
APR_BLOCK_READ and APR_NONBLOCK_READ enums in apr-util.  This
applies to sockets and pipes on Unix (no idea about Win32).

When the APR socket timeout is < 0, we use a blocking socket.
When the APR socket timeout is >=0, we use a non-blocking socket.

When the timeout is >0 (hence non-blocking) and read() doesn't
return any data, we call apr_wait_for_io_or_timeout() to wait for the
timeout value.  So, the result is that if the timeout value is 0, we
return immediately (one-shot non-blocking read).

APR_BLOCK_READ indicates that the read should wait for the socket's
*timeout* period for data.  It leaves the timeout values alone.  So,
per the socket timeout rules above, if the timeout < 0, then it will
wait indefinitely.  If the timeout is > 0, then we will wait for the
timeout.  And, if the timeout is 0 and APR_BLOCK_READ is called, it
essentially becomes APR_NONBLOCK_READ (see next).

APR_NONBLOCK_READ indicates that the read() should return immediately
in any case.  It should *never* block.  The timeouts don't apply.

So, if your application was using APR_NONBLOCK_READ and expected it
to wait for the timeout period, then it should have been using
APR_BLOCK_READ.  Brad pointed out mod_cgi.c as his example case, but
that uses APR_BLOCK_READ (per above, uses a non-blocking pipe with a
timeout).  So, the timeout value that mod_cgi sets is respected.

I hope this eliminates the confusion.  -- justin

View raw message