summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwrowe <wrowe@13f79535-47bb-0310-9956-ffa450edef68>2008-05-01 22:24:14 +0000
committerwrowe <wrowe@13f79535-47bb-0310-9956-ffa450edef68>2008-05-01 22:24:14 +0000
commitf1262abe3cd6159cfb22c4ca25036d7cab93e8ae (patch)
treea3833e8a15c17a9dc2cf510ebbbbd4b857c63aae
parent65575b18662aff82fbfc95a3c827d347c9bce418 (diff)
downloadlibapr-f1262abe3cd6159cfb22c4ca25036d7cab93e8ae.tar.gz
Reflow the OS/X sendfile implementation to proceed from writev(hd..iovec)
to the sendfile/tr..iovec series, tallying these correctly. Submitted by: Geoff Greer <angryparsley mipsisrisc.com> and wrowe Backports: r652690 git-svn-id: http://svn.apache.org/repos/asf/apr/apr/branches/1.3.x@652691 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--network_io/unix/sendrecv.c39
1 files changed, 23 insertions, 16 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c
index 3b43508c2..39dd199e7 100644
--- a/network_io/unix/sendrecv.c
+++ b/network_io/unix/sendrecv.c
@@ -413,7 +413,8 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
apr_off_t nbytes = 0;
apr_off_t bytes_to_send = *len;
apr_size_t header_bytes_written = 0;
- int rv;
+ int rv = 0;
+ int sent_headers = 0;
/* Ignore flags for now. */
flags = 0;
@@ -436,17 +437,24 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
return arv;
}
}
-
- if (hdtr->numheaders) {
- rv = writev(sock->socketdes,
- hdtr->headers,
- hdtr->numheaders);
- if (rv > 0) {
- header_bytes_written = rv;
- rv = 0;
+
+ if (!sent_headers) {
+ if (hdtr->numheaders) {
+ rv = writev(sock->socketdes,
+ hdtr->headers,
+ hdtr->numheaders);
+ if (rv > 0) {
+ header_bytes_written = rv;
+ sent_headers = 1;
+ rv = 0;
+ }
+ }
+ else {
+ sent_headers = 1;
}
}
- else if (bytes_to_send) {
+
+ if (bytes_to_send && sent_headers) {
/* We won't dare call sendfile() if we don't have
* header or file bytes to send because nbytes == 0
* means send the remaining file to EOF.
@@ -464,12 +472,13 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
if (errno == EAGAIN) {
if (sock->timeout > 0) {
sock->options |= APR_INCOMPLETE_WRITE;
+ rv = 0;
}
/* BSD'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 (nbytes) {
+ else if (nbytes) {
/* normal exit for a big file & non-blocking io */
(*len) = nbytes + header_bytes_written;
return APR_SUCCESS;
@@ -486,19 +495,17 @@ apr_status_t apr_socket_sendfile(apr_socket_t * sock, apr_file_t * file,
}
}
}
- else {
+
+ if (sent_headers && !bytes_to_send) {
/* just trailer bytes... use writev()
*/
rv = writev(sock->socketdes,
hdtr->trailers,
hdtr->numtrailers);
if (rv > 0) {
- nbytes = rv;
+ nbytes += rv;
rv = 0;
}
- else {
- nbytes = 0;
- }
}
if ((rv == -1) && (errno == EAGAIN)
&& (sock->timeout > 0)) {