[PATCH / v4] SPDY: fix nopush cleanup

Yury Kirpichev ykirpichev at gmail.com
Mon Jun 17 08:52:06 UTC 2013


Hi,

Please disregard v3 version of patch. I've found that it does not fix the
problem in case if some data was buffered and afterwards was sent by
"write" handler.

Here is new version:
# HG changeset patch
# User ykirpichev at yandex-team.ru
# Date 1371458549 -14400
# Branch nopush_fix
# Node ID 3d463c13dadd70b3f74cbc037938c624db348cc0
# Parent  982678c5c270f93a0c21ab6eb23cb123c0dc3df0
SPDY: fix nopush cleanup

diff -r 982678c5c270 -r 3d463c13dadd src/http/ngx_http_spdy.c
--- a/src/http/ngx_http_spdy.c Wed Jun 12 00:41:24 2013 +0900
+++ b/src/http/ngx_http_spdy.c Mon Jun 17 12:42:29 2013 +0400
@@ -154,6 +154,8 @@

 static void *ngx_http_spdy_zalloc(void *opaque, u_int items, u_int size);
 static void ngx_http_spdy_zfree(void *opaque, void *address);
+static ngx_int_t
+ngx_http_spdy_restore_nopush(ngx_connection_t *c, ngx_http_connection_t
*hc);


 static const u_char ngx_http_spdy_dict[] =
@@ -378,6 +380,11 @@

     sc->blocked = 0;

+    if (ngx_http_spdy_restore_nopush(c, sc->http_connection) != NGX_OK) {
+        ngx_http_spdy_finalize_connection(sc,
NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return;
+    }
+
     if (sc->processing) {
         if (rev->timer_set) {
             ngx_del_timer(rev);
@@ -447,6 +454,11 @@
         return;
     }

+    if (ngx_http_spdy_restore_nopush(c, sc->http_connection) != NGX_OK) {
+        ngx_http_spdy_finalize_connection(sc,
NGX_HTTP_INTERNAL_SERVER_ERROR);
+        return;
+    }
+
     ngx_http_spdy_handle_connection(sc);
 }

@@ -2880,3 +2892,61 @@
                    "spdy zfree: %p", address);
 #endif
 }
+
+static ngx_int_t
+ngx_http_spdy_restore_nopush(ngx_connection_t *c, ngx_http_connection_t
*hc)
+{
+    int                      tcp_nodelay;
+    ngx_http_core_loc_conf_t *clcf;
+
+    // It is better to use NGX_SPDY_WRITE_BUFFERED here, but
+    // it is defined in ngx_http_spdy_filter_module.c
+    // So, just use !c->buffered
+    if (!c->buffered && !c->error) {
+        //no buffered data, so, we should clean nopush if needed
+        clcf = ngx_http_get_module_loc_conf(hc->conf_ctx,
+                                            ngx_http_core_module);
+
+        if (c->tcp_nopush == NGX_TCP_NOPUSH_SET) {
+            if (ngx_tcp_push(c->fd) == -1) {
+                ngx_connection_error(c, ngx_socket_errno, ngx_tcp_push_n "
failed");
+                return NGX_ERROR;
+            }
+
+            c->tcp_nopush = NGX_TCP_NOPUSH_UNSET;
+            tcp_nodelay = ngx_tcp_nodelay_and_tcp_nopush ? 1 : 0;
+
+        } else {
+            tcp_nodelay = 1;
+        }
+
+        if (tcp_nodelay
+            && clcf->tcp_nodelay
+            && c->tcp_nodelay == NGX_TCP_NODELAY_UNSET)
+        {
+            ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "tcp_nodelay");
+
+            if (setsockopt(c->fd, IPPROTO_TCP, TCP_NODELAY,
+                           (const void *) &tcp_nodelay, sizeof(int))
+                == -1)
+            {
+#if (NGX_SOLARIS)
+                /* Solaris returns EINVAL if a socket has been shut down */
+                c->log_error = NGX_ERROR_IGNORE_EINVAL;
+#endif
+
+                ngx_connection_error(c, ngx_socket_errno,
+                                     "setsockopt(TCP_NODELAY) failed");
+
+                c->log_error = NGX_ERROR_INFO;
+                return NGX_ERROR;
+            }
+
+            c->tcp_nodelay = NGX_TCP_NODELAY_SET;
+        }
+    }
+
+    return NGX_OK;
+}
+
+
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130617/a2f06c9a/attachment.html>


More information about the nginx-devel mailing list