Rather than waiting for IO to be possible, doesn't the sendfile() return the
number of bytes written? In other words, you would get EAGAIN *and* bytes
written. Thus, you know not to send that data again.

Seems like that would save a syscall for calls with timeout > 0.

Cheers,
-g

On Fri, Dec 22, 2000 at 12:19:17AM -0000, [EMAIL PROTECTED] wrote:
> rbb         00/12/21 16:19:17
> 
>   Modified:    .        CHANGES
>                network_io/unix sendrecv.c
>   Log:
>   On FreeBSD, it is possible for the first call to sendfile to
>   get 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.  If we are using a timed write, then we check to make sure
>   we can send data before trying to send it.  This gets sendfile working
>   on FreeBSD in Apache again.
>   
>   Revision  Changes    Path
>   1.30      +8 -0      apr/CHANGES
>   
>   Index: CHANGES
>   ===================================================================
>   RCS file: /home/cvs/apr/CHANGES,v
>   retrieving revision 1.29
>   retrieving revision 1.30
>   diff -u -r1.29 -r1.30
>   --- CHANGES 2000/12/22 00:02:49     1.29
>   +++ CHANGES 2000/12/22 00:19:14     1.30
>   @@ -1,5 +1,13 @@
>    Changes with APR b1
>    
>   +  *) On FreeBSD, it is possible for the first call to sendfile to
>   +     get 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.  If we are using a timed write, then we check to make sure
>   +     we can send data before trying to send it. [Ryan Bloom]
>   +
>      *) Cleanup to help Apache support programs build cleanly.
>         [Cliff Woolley <[EMAIL PROTECTED]>]
>    
>   
>   
>   
>   1.52      +15 -22    apr/network_io/unix/sendrecv.c
>   
>   Index: sendrecv.c
>   ===================================================================
>   RCS file: /home/cvs/apr/network_io/unix/sendrecv.c,v
>   retrieving revision 1.51
>   retrieving revision 1.52
>   diff -u -r1.51 -r1.52
>   --- sendrecv.c      2000/11/17 04:19:18     1.51
>   +++ sendrecv.c      2000/12/22 00:19:16     1.52
>   @@ -412,6 +412,21 @@
>        headerstruct.trl_cnt = hdtr->numtrailers;
>    
>        /* FreeBSD can send the headers/footers as part of the system call */
>   +    if (sock->timeout > 0) {
>   +        /* On FreeBSD, it is possible for the first call to sendfile to
>   +         * get 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.  If we are using a timed write, then we check to make 
> sure
>   +         * we can send data before trying to send it.
>   +         */
>   +        apr_status_t arv = wait_for_io_or_timeout(sock, 0);
>   +        if (arv != APR_SUCCESS) {
>   +            *len = 0;
>   +            return arv;
>   +        }
>   +    }
>    
>        do {
>            if (bytes_to_send) {
>   @@ -442,28 +457,6 @@
>                }
>            }
>        } while (rv == -1 && errno == EINTR);
>   -
>   -    if (rv == -1 && 
>   -        (errno == EAGAIN || errno == EWOULDBLOCK) && 
>   -        sock->timeout > 0) {
>   -   apr_status_t arv = wait_for_io_or_timeout(sock, 0);
>   -   if (arv != APR_SUCCESS) {
>   -       *len = 0;
>   -       return arv;
>   -   }
>   -        else {
>   -            do {
>   -           rv = sendfile(file->filedes,    /* open file descriptor of the 
> file to be sent */
>   -                         sock->socketdes,  /* socket */
>   -                         *offset,  /* where in the file to start */
>   -                         (size_t) * len,   /* number of bytes to send */
>   -                         &headerstruct,    /* Headers/footers */
>   -                         &nbytes,  /* number of bytes written */
>   -                         flags     /* undefined, set to 0 */
>   -               );
>   -            } while (rv == -1 && errno == EINTR);
>   -        }
>   -    }
>    
>        (*len) = nbytes;
>        if (rv == -1) {
>   
>   
>   

-- 
Greg Stein, http://www.lyra.org/

Reply via email to