Return-Path: Delivered-To: apmail-apr-cvs-archive@apr.apache.org Received: (qmail 29718 invoked by uid 500); 24 Jul 2001 16:56:23 -0000 Mailing-List: contact cvs-help@apr.apache.org; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: Reply-To: dev@apr.apache.org Delivered-To: mailing list cvs@apr.apache.org Received: (qmail 29696 invoked from network); 24 Jul 2001 16:56:23 -0000 Date: 24 Jul 2001 16:53:40 -0000 Message-ID: <20010724165340.493.qmail@icarus.apache.org> From: jerenkrantz@apache.org To: apr-cvs@apache.org Subject: cvs commit: apr/network_io/unix sendrecv.c X-Spam-Rating: h31.sny.collab.net 1.6.2 0/1000/N jerenkrantz 01/07/24 09:53:40 Modified: network_io/unix sendrecv.c Log: Move the blocking logic on FreeBSD to match everyone else to be after the sendfile() call rather than before. Redid the comment to make a bit more sense given its new location. Someone who has FreeBSD will need to make sure this still works as expected. Revision Changes Path 1.70 +21 -20 apr/network_io/unix/sendrecv.c Index: sendrecv.c =================================================================== RCS file: /home/cvs/apr/network_io/unix/sendrecv.c,v retrieving revision 1.69 retrieving revision 1.70 diff -u -r1.69 -r1.70 --- sendrecv.c 2001/07/24 16:37:23 1.69 +++ sendrecv.c 2001/07/24 16:53:40 1.70 @@ -410,26 +410,6 @@ 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. - * - * JLT: doing this first doesn't eliminate the possibility that - * we get -1/EAGAIN/nbytes>0; AFAICT it just means extra syscalls - * from time to time - */ - apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); - if (arv != APR_SUCCESS) { - *len = 0; - return arv; - } - } - do { if (bytes_to_send) { /* We won't dare call sendfile() if we don't have @@ -466,6 +446,27 @@ } } } 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) { + apr_status_t arv = apr_wait_for_io_or_timeout(sock, 0); + if (arv != APR_SUCCESS) { + *len = 0; + return arv; + } + } (*len) = nbytes; if (rv == -1) {