On Mon, Sep 17, 2018 at 3:27 PM Yann Ylavic <[email protected]> wrote:
>
> Otherwise, you need a patch like the one attached (untested)...
Sorry, it did not compile, so here is v2.
With this patch, you could compile httpd with "-D
MAX_BYTES_TO_WRITEV=52000" for instance.
Index: server/core_filters.c
===================================================================
--- server/core_filters.c (revision 1840698)
+++ server/core_filters.c (working copy)
@@ -348,6 +348,7 @@ static apr_status_t send_brigade_blocking(apr_sock
static apr_status_t writev_nonblocking(apr_socket_t *s,
struct iovec *vec, apr_size_t nvec,
apr_bucket_brigade *bb,
+ apr_size_t bytes_to_write,
apr_size_t *cumulative_bytes_written,
conn_rec *c);
@@ -645,6 +646,9 @@ static void setaside_remaining_output(ap_filter_t
#define MAX_IOVEC_TO_WRITE APR_MAX_IOVEC_SIZE
#endif
#endif
+#ifndef MAX_BYTES_TO_WRITEV
+#define MAX_BYTES_TO_WRITEV 0
+#endif
static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
apr_bucket_brigade *bb,
@@ -654,7 +658,7 @@ static apr_status_t send_brigade_nonblocking(apr_s
apr_bucket *bucket, *next;
apr_status_t rv;
struct iovec vec[MAX_IOVEC_TO_WRITE];
- apr_size_t nvec = 0;
+ apr_size_t nvec = 0, nbytes = 0;
remove_empty_buckets(bb);
@@ -676,11 +680,12 @@ static apr_status_t send_brigade_nonblocking(apr_s
(bucket->length >= AP_MIN_SENDFILE_BYTES)) {
if (nvec > 0) {
(void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
- rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
+ rv = writev_nonblocking(s, vec, nvec, bb, nbytes, bytes_written, c);
if (rv != APR_SUCCESS) {
(void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
return rv;
}
+ nbytes = 0;
}
rv = sendfile_nonblocking(s, bucket, bytes_written, c);
if (nvec > 0) {
@@ -705,10 +710,11 @@ static apr_status_t send_brigade_nonblocking(apr_s
if (APR_STATUS_IS_EAGAIN(rv)) {
/* Read would block; flush any pending data and retry. */
if (nvec) {
- rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
+ rv = writev_nonblocking(s, vec, nvec, bb, nbytes, bytes_written, c);
if (rv) {
return rv;
}
+ nbytes = 0;
nvec = 0;
}
@@ -717,25 +723,42 @@ static apr_status_t send_brigade_nonblocking(apr_s
if (rv != APR_SUCCESS) {
return rv;
}
+ if (!length) {
+ /* read may have split the bucket, so recompute next: */
+ next = APR_BUCKET_NEXT(bucket);
+ continue;
+ }
- /* reading may have split the bucket, so recompute next: */
+ nbytes += length;
+#if MAX_BYTES_TO_WRITEV
+ if (nbytes > MAX_BYTES_TO_WRITEV) {
+ length -= nbytes - MAX_BYTES_TO_WRITEV;
+ rv = apr_bucket_split(bucket, length);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+ nbytes = MAX_BYTES_TO_WRITEV;
+ }
+#endif
+
+ /* above may have split the bucket, so recompute next: */
next = APR_BUCKET_NEXT(bucket);
vec[nvec].iov_base = (char *)data;
vec[nvec].iov_len = length;
nvec++;
- if (nvec == MAX_IOVEC_TO_WRITE) {
- rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
- nvec = 0;
+ if (nvec == MAX_IOVEC_TO_WRITE || nbytes == MAX_BYTES_TO_WRITEV) {
+ rv = writev_nonblocking(s, vec, nvec, bb, nbytes, bytes_written, c);
if (rv != APR_SUCCESS) {
return rv;
}
- break;
+ nbytes = 0;
+ nvec = 0;
}
}
}
if (nvec > 0) {
- rv = writev_nonblocking(s, vec, nvec, bb, bytes_written, c);
+ rv = writev_nonblocking(s, vec, nvec, bb, nbytes, bytes_written, c);
if (rv != APR_SUCCESS) {
return rv;
}
@@ -795,11 +818,12 @@ static apr_status_t send_brigade_blocking(apr_sock
static apr_status_t writev_nonblocking(apr_socket_t *s,
struct iovec *vec, apr_size_t nvec,
apr_bucket_brigade *bb,
+ apr_size_t bytes_to_write,
apr_size_t *cumulative_bytes_written,
conn_rec *c)
{
apr_status_t rv = APR_SUCCESS, arv;
- apr_size_t bytes_written = 0, bytes_to_write = 0;
+ apr_size_t bytes_written = 0;
apr_size_t i, offset;
apr_interval_time_t old_timeout;
@@ -812,9 +836,6 @@ static apr_status_t writev_nonblocking(apr_socket_
return arv;
}
- for (i = 0; i < nvec; i++) {
- bytes_to_write += vec[i].iov_len;
- }
offset = 0;
while (bytes_written < bytes_to_write) {
apr_size_t n = 0;
@@ -823,7 +844,7 @@ static apr_status_t writev_nonblocking(apr_socket_
bytes_written += n;
for (i = offset; i < nvec; ) {
apr_bucket *bucket = APR_BRIGADE_FIRST(bb);
- if (APR_BUCKET_IS_METADATA(bucket)) {
+ if (APR_BUCKET_IS_METADATA(bucket) || !bucket->length) {
apr_bucket_delete(bucket);
}
else if (n >= vec[i].iov_len) {
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]