]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
core: Disable TCP_NOPUSH optimization on OSX. BZ 66019.
authorYann Ylavic <ylavic@apache.org>
Tue, 24 May 2022 09:03:30 +0000 (09:03 +0000)
committerYann Ylavic <ylavic@apache.org>
Tue, 24 May 2022 09:03:30 +0000 (09:03 +0000)
OSX supports TCP_NOPUSH but does not release the data retained (in TCP stack)
when the option is unset. It seems that unsetting it before the last write
does not help either so just disable the optimization for OSX in the core
output filter to avoid uncontrollable transmission delays.

* server/core_filters.c():
  Add the sock_nopush() helper that does nothing on OSX and platforms not
  supporting TCP_NOPUSH or TCP_CORK.

* server/core_filters.c(send_brigade_nonblocking):
  Use sock_nopush() instead of apr_socket_opt_set() for APR_TCP_NOPUSH option.

Merge r1900100 from trunk.

Submitted by: ylavic
Reviewed by: ylavic, rpluem, jorton

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1901201 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
server/core_filters.c

diff --git a/CHANGES b/CHANGES
index 30213a57072ef347b7a7952b46a2e5179b884258..20d9e60a66b314f364afd4f79c81d71ba1103632 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,6 +1,9 @@
                                                          -*- coding: utf-8 -*-
 Changes with Apache 2.4.54
 
+  *) core: Disable TCP_NOPUSH optimization on OSX since it might introduce
+     transmission delays.  PR 66019.  [Yann Ylavic]
+
   *) MPM event: Fix accounting of active/total processes on ungraceful restart,
      PR 66004 (follow up to PR 65626 from 2.4.52).  [Yann Ylavic]
 
index d81ffc97229c921a66c35fc2979dfb0bec00c25f..50a6b8d1371726876ec1f9320cfef67ac55aa4a3 100644 (file)
@@ -628,6 +628,18 @@ static APR_INLINE int can_sendfile_bucket(apr_bucket *b)
 }
 #endif
 
+static APR_INLINE void sock_nopush(apr_socket_t *s, int to)
+{
+    /* Disable TCP_NOPUSH handling on OSX since unsetting it won't push
+     * retained data, which might introduce delays if further data don't
+     * come soon enough or cause the last chunk to be sent only when the
+     * connection is shutdown (e.g. after KeepAliveTimeout).
+     */
+#if APR_TCP_NOPUSH_FLAG && !defined(__APPLE__)
+    (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, to);
+#endif
+}
+
 static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
                                              apr_bucket_brigade *bb,
                                              core_output_filter_ctx_t *ctx,
@@ -649,7 +661,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
 #if APR_HAS_SENDFILE
         if (can_sendfile_bucket(bucket)) {
             if (nvec > 0) {
-                (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
+                sock_nopush(s, 1);
                 rv = writev_nonblocking(s, bb, ctx, nbytes, nvec, c);
                 if (rv != APR_SUCCESS) {
                     goto cleanup;
@@ -679,7 +691,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
                     nbytes = 0;
                     nvec = 0;
                 }
-                (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
+                sock_nopush(s, 0);
 
                 rv = apr_bucket_read(bucket, &data, &length, APR_BLOCK_READ);
             }
@@ -707,7 +719,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
         /* Make sure that these new data fit in our iovec. */
         if (nvec == ctx->nvec) {
             if (nvec == NVEC_MAX) {
-                (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
+                sock_nopush(s, 1);
                 rv = writev_nonblocking(s, bb, ctx, nbytes, nvec, c);
                 if (rv != APR_SUCCESS) {
                     goto cleanup;
@@ -745,7 +757,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
         if (nbytes > conf->flush_max_threshold
                 && next != APR_BRIGADE_SENTINEL(bb)
                 && !is_in_memory_bucket(next)) {
-            (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 1);
+            sock_nopush(s, 1);
             rv = writev_nonblocking(s, bb, ctx, nbytes, nvec, c);
             if (rv != APR_SUCCESS) {
                 goto cleanup;
@@ -759,7 +771,7 @@ static apr_status_t send_brigade_nonblocking(apr_socket_t *s,
     }
 
 cleanup:
-    (void)apr_socket_opt_set(s, APR_TCP_NOPUSH, 0);
+    sock_nopush(s, 0);
     return rv;
 }