httpd-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Jeff Trawick <traw...@attglobal.net>
Subject Re: Apache/2.0.22-dev is running on apache.org
Date Wed, 25 Jul 2001 20:12:13 GMT
Jeff Trawick <trawick@attglobal.net> writes:

> Greg Ames <gregames@remulak.net> writes:
> 
> > But what if we have rv == -1, EAGAIN, and nbytes == 0 ?  I don't think
> > we handle that properly yet in FreeBSD, nor in Solaris.  Looks to me
> > like the new FreeBSD code will exit apr_sendfile with APR_EAGAIN, and
> > sendfile_it_all will bail, and the request will die.  
> 
> yeah, it definitely looks busted...  I'll work on that...

Here is a patch for FreeBSD which I'll commit soon if nobody
complains.  It fixes a few problems with when we call
wait_for_io_or_timeout(), and it also tries to send again when
wait_for_io_or_timeout() succeeds.

Index: srclib/apr/network_io/unix/sendrecv.c
===================================================================
RCS file: /home/cvspublic/apr/network_io/unix/sendrecv.c,v
retrieving revision 1.71
diff -u -r1.71 sendrecv.c
--- srclib/apr/network_io/unix/sendrecv.c	2001/07/25 05:27:32	1.71
+++ srclib/apr/network_io/unix/sendrecv.c	2001/07/25 20:04:59
@@ -447,24 +447,51 @@
         }
     } while (rv == -1 && errno == EINTR);
 
-    /* On FreeBSD, it is possible that sendfile will return EAGAIN, but 
-     * still send some data.  This means that we cannot call sendfile 
-     * and then check for EAGAIN, and then wait and call sendfile again.
-     * If we do that, then we are likely to send the first chunk of data 
-     * twice, once in the first call and once in the second.
-     *
-     * When we are dealing with a non-blocking or timeout socket, the
-     * caller must already be aware that we may not be able to write
-     * everything in one call.  Therefore, we should return back to
-     * the caller with how much we actually sent (as specified from EAGAIN).
-     *
-     * If we are using a timed write, we will now block until we are clear.
-     */
-    if (errno == EAGAIN && nbytes && sock->timeout >= 0) {
+    if (rv == -1 &&
+        errno == EAGAIN && 
+        sock->timeout > 0) {
         apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0);
         if (arv != APR_SUCCESS) {
             *len = 0;
             return arv;
+        }
+        else {
+            do {
+                if (bytes_to_send) {
+                    /* We won't dare call sendfile() if we don't have
+                     * header or file bytes to send because bytes_to_send == 0
+                     * means send the whole file.
+                     */
+                    rv = sendfile(file->filedes, /* file to be sent */
+                                  sock->socketdes, /* socket */
+                                  *offset,       /* where in the file to start */
+                                  bytes_to_send, /* number of bytes to send */
+                                  &headerstruct, /* Headers/footers */
+                                  &nbytes,       /* number of bytes written */
+                                  flags);        /* undefined, set to 0 */
+                    /* FreeBSD's sendfile can return -1/EAGAIN even if it
+                     * sent bytes.  Sanitize the result so we get normal EAGAIN
+                     * semantics w.r.t. bytes sent.
+                     */
+                    if (rv == -1 && errno == EAGAIN && nbytes) {
+                        rv = 0;
+                    }
+                }
+                else {
+                    /* just trailer bytes... use writev()
+                     */
+                    rv = writev(sock->socketdes,
+                                hdtr->trailers,
+                                hdtr->numtrailers);
+                    if (rv > 0) {
+                        nbytes = rv;
+                        rv = 0;
+                    }
+                    else {
+                        nbytes = 0;
+                    }
+                }
+            } while (rv == -1 && errno == EINTR);
         }
     }
 

-- 
Jeff Trawick | trawick@attglobal.net | PGP public key at web site:
       http://www.geocities.com/SiliconValley/Park/9289/
             Born in Roswell... married an alien...

Mime
View raw message