diff options
author | jerenkrantz <jerenkrantz@13f79535-47bb-0310-9956-ffa450edef68> | 2001-07-24 16:37:23 +0000 |
---|---|---|
committer | jerenkrantz <jerenkrantz@13f79535-47bb-0310-9956-ffa450edef68> | 2001-07-24 16:37:23 +0000 |
commit | eb8c1ec39c319b3399587414e270dc5d53a09483 (patch) | |
tree | dcfed928db53a97d5d0b921813b363a100dd471f | |
parent | 521d174ac08b7a248f79b20fc5dc8ac5358a2aed (diff) | |
download | libapr-eb8c1ec39c319b3399587414e270dc5d53a09483.tar.gz |
Bring the Solaris sendfilev() in line with the rest of the code in that
it will block after receiving an EAGAIN instead of before the sendfilev().
However, both Solaris and FreeBSD will return EAGAIN even if the write
was successful. This makes it a bit awkward to block after the write
(hence why FreeBSD does it the way it does). Other platforms will
return EAGAIN without having sent anything - after the wait_for_io returns
they need to recall their sendfile. Solaris and FreeBSD can just continue
on their merry way.
- Update *len to be zero when we get an error - the others seem to do this.
- Only wait when it is a timeout not if it is a true non-blocking socket.
git-svn-id: http://svn.apache.org/repos/asf/apr/apr/trunk@62011 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | network_io/unix/sendrecv.c | 42 |
1 files changed, 30 insertions, 12 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c index caed10889..a9b0d7db7 100644 --- a/network_io/unix/sendrecv.c +++ b/network_io/unix/sendrecv.c @@ -805,24 +805,42 @@ apr_status_t apr_sendfile(apr_socket_t *sock, apr_file_t *file, sfv[curvec].sfv_len = hdtr->trailers[i].iov_len; } - /* If we are in non-blocking mode, we need to make sure we wait until - * the other side says it is okay. */ - if (apr_is_option_set(sock->netmask, APR_SO_NONBLOCK) == 1 || - apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) == 1) - { - rv = apr_wait_for_io_or_timeout(sock, 0); - } - /* Actually do the sendfilev */ do { /* socket, vecs, number of vecs, bytes written */ rv = sendfilev(sock->socketdes, sfv, vecs, &nbytes); } while (rv == -1 && errno == EINTR); - /* Solaris returns EAGAIN even though it sent bytes on a non-block sock */ - if (rv == -1 && errno != EAGAIN) { - rv = errno; - return rv; + /* Solaris returns EAGAIN even though it sent bytes on a non-block sock. + * However, if we are on a TIMEOUT socket, we want to block until the + * other side has read the data. + */ + if (rv == -1) + { + if (errno == EAGAIN) { + if (apr_is_option_set(sock->netmask, APR_SO_TIMEOUT) == 1) + { + /* If the wait fails for some reason, we're going to lie to our + * caller and say that we didn't write any bytes. That's + * untrue. + */ + rv = apr_wait_for_io_or_timeout(sock, 0); + + /* Indicate that we sent zero bytes. */ + if (rv != APR_SUCCESS) + { + *len = 0; + return rv; + } + } + } + else + { + /* Indicate that we sent zero bytes. */ + rv = errno; + *len = 0; + return rv; + } } /* Update how much we sent */ |