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) {