summaryrefslogtreecommitdiff
path: root/network_io
diff options
context:
space:
mode:
authorYann Ylavic <ylavic@apache.org>2022-06-28 11:23:22 +0000
committerYann Ylavic <ylavic@apache.org>2022-06-28 11:23:22 +0000
commit443a5314045169047070ad3a32e5134227d837dd (patch)
tree7e2f9ec838b67e797d4e05a6cbe258d17b4c5796 /network_io
parent27046d793026738b08478b86e29060a8a0533b32 (diff)
downloadapr-443a5314045169047070ad3a32e5134227d837dd.tar.gz
apr_socket_sendv: unix: APR_INCOMPLETE_WRITE pre to post processing.
Rather than precomputing requested_len before writev() and later comparing with what has been sent, we can walk the iovec after only to see if it's exhausted. This saves useless precomputation on error (e.g. nonblocking EAGAIN) and avoids a poteential invalid/overflowed requested_len should the iovec point to more than SIZE_MAX bytes. git-svn-id: https://svn.apache.org/repos/asf/apr/apr/trunk@1902314 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'network_io')
-rw-r--r--network_io/unix/sendrecv.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/network_io/unix/sendrecv.c b/network_io/unix/sendrecv.c
index b9e580b1b..1b965af50 100644
--- a/network_io/unix/sendrecv.c
+++ b/network_io/unix/sendrecv.c
@@ -196,13 +196,8 @@ apr_status_t apr_socket_sendv(apr_socket_t * sock, const struct iovec *vec,
{
#ifdef HAVE_WRITEV
apr_ssize_t rv;
- apr_size_t requested_len = 0;
apr_int32_t i;
- for (i = 0; i < nvec; i++) {
- requested_len += vec[i].iov_len;
- }
-
if (sock->options & APR_INCOMPLETE_WRITE) {
sock->options &= ~APR_INCOMPLETE_WRITE;
goto do_select;
@@ -231,8 +226,16 @@ do_select:
*len = 0;
return errno;
}
- if ((sock->timeout > 0) && (rv < requested_len)) {
- sock->options |= APR_INCOMPLETE_WRITE;
+ if (sock->timeout > 0) {
+ apr_size_t rv_len = rv;
+ for (i = 0; i < nvec; ++i) {
+ apr_size_t iov_len = vec[i].iov_len;
+ if (rv_len < iov_len) {
+ sock->options |= APR_INCOMPLETE_WRITE;
+ break;
+ }
+ rv_len -= iov_len;
+ }
}
(*len) = rv;
return APR_SUCCESS;