You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by bc...@apache.org on 2016/10/06 00:04:47 UTC

[trafficserver] branch 7.0.x updated: TS-4813: Fix lingering stream.

This is an automated email from the ASF dual-hosted git repository.

bcall pushed a commit to branch 7.0.x
in repository https://git-dual.apache.org/repos/asf/trafficserver.git

The following commit(s) were added to refs/heads/7.0.x by this push:
       new  8dc35e0   TS-4813: Fix lingering stream.
8dc35e0 is described below

commit 8dc35e04a8a0b4fb6b1ea2bebcfaa915e7acdbf5
Author: Susan Hinrichs <sh...@ieee.org>
AuthorDate: Tue Sep 27 16:24:11 2016 +0000

    TS-4813: Fix lingering stream.
    
    (cherry picked from commit dc8be341578aa0fa900c84265d0a336414dfad9b)
---
 iocore/net/SSLNetVConnection.cc     | 18 ++++++++++------
 proxy/http/HttpTunnel.cc            | 20 +++++++++---------
 proxy/http2/Http2ConnectionState.cc | 41 ++++++++++++++++++++++---------------
 proxy/http2/Http2Stream.cc          |  2 +-
 4 files changed, 48 insertions(+), 33 deletions(-)

diff --git a/iocore/net/SSLNetVConnection.cc b/iocore/net/SSLNetVConnection.cc
index 2e96eb3..39243c8 100644
--- a/iocore/net/SSLNetVConnection.cc
+++ b/iocore/net/SSLNetVConnection.cc
@@ -349,12 +349,18 @@ SSLNetVConnection::read_raw_data()
         b = b->next.get();
       }
 
-      ink_assert(niov > 0);
-      ink_assert(niov <= countof(tiovec));
-      r = socketManager.readv(this->con.fd, &tiovec[0], niov);
-
-      NET_INCREMENT_DYN_STAT(net_calls_to_read_stat);
-      total_read += rattempted;
+      // If there was no room to write into the buffer then skip the read
+      if (niov > 0) {
+        ink_assert(niov > 0);
+        ink_assert(niov <= countof(tiovec));
+        r = socketManager.readv(this->con.fd, &tiovec[0], niov);
+
+        NET_INCREMENT_DYN_STAT(net_calls_to_read_stat);
+        total_read += rattempted;
+      } else { // No more space to write, break out
+        r = 0;
+        break;
+      }
     } while (rattempted && r == rattempted && total_read < toread);
 
     // if we have already moved some bytes successfully, summarize in r
diff --git a/proxy/http/HttpTunnel.cc b/proxy/http/HttpTunnel.cc
index b018cae..9b1b0aa 100644
--- a/proxy/http/HttpTunnel.cc
+++ b/proxy/http/HttpTunnel.cc
@@ -1211,8 +1211,6 @@ HttpTunnel::producer_handler(int event, HttpTunnelProducer *p)
 
   Debug("http_redirect", "[HttpTunnel::producer_handler] enable_redirection: [%d %d %d] event: %d", p->alive == true,
         sm->enable_redirection, (p->self_consumer && p->self_consumer->alive == true), event);
-  ink_assert(p->alive == true || event == HTTP_TUNNEL_EVENT_PRECOMPLETE || event == VC_EVENT_EOS || sm->enable_redirection ||
-             (p->self_consumer && p->self_consumer->alive == true));
 
   switch (event) {
   case VC_EVENT_READ_READY:
@@ -1268,14 +1266,16 @@ HttpTunnel::producer_handler(int event, HttpTunnelProducer *p)
   case VC_EVENT_ACTIVE_TIMEOUT:
   case VC_EVENT_INACTIVITY_TIMEOUT:
   case HTTP_TUNNEL_EVENT_CONSUMER_DETACH:
-    p->alive      = false;
-    p->bytes_read = p->read_vio->ndone;
-    // Interesting tunnel event, call SM
-    jump_point = p->vc_handler;
-    (sm->*jump_point)(event, p);
-    sm_callback = true;
-    // Failure case anyway
-    p->update_state_if_not_set(HTTP_SM_POST_UA_FAIL);
+    if (p->alive) {
+      p->alive      = false;
+      p->bytes_read = p->read_vio->ndone;
+      // Interesting tunnel event, call SM
+      jump_point = p->vc_handler;
+      (sm->*jump_point)(event, p);
+      sm_callback = true;
+      // Failure case anyway
+      p->update_state_if_not_set(HTTP_SM_POST_UA_FAIL);
+    }
     break;
 
   case VC_EVENT_WRITE_READY:
diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc
index 212536e..1fd0f88 100644
--- a/proxy/http2/Http2ConnectionState.cc
+++ b/proxy/http2/Http2ConnectionState.cc
@@ -797,6 +797,7 @@ Http2ConnectionState::main_event_handler(int event, void *edata)
 
   // Finalize HTTP/2 Connection
   case HTTP2_SESSION_EVENT_FINI: {
+    ink_assert(this->fini_received == false);
     this->fini_received = true;
     cleanup_streams();
     SET_HANDLER(&Http2ConnectionState::state_closed);
@@ -964,9 +965,8 @@ Http2ConnectionState::cleanup_streams()
     this->delete_stream(s);
     s = next;
   }
+  ink_assert(stream_list.head == NULL);
 
-  client_streams_in_count  = 0;
-  client_streams_out_count = 0;
   if (!is_state_closed()) {
     ua_session->get_netvc()->add_to_keep_alive_queue();
     ua_session->get_netvc()->cancel_active_timeout();
@@ -976,6 +976,11 @@ Http2ConnectionState::cleanup_streams()
 void
 Http2ConnectionState::delete_stream(Http2Stream *stream)
 {
+  // If stream has already been removed from the list, just go on
+  if (!stream_list.in(stream)) {
+    return;
+  }
+
   DebugHttp2Stream(ua_session, stream->get_id(), "Delete stream");
 
   if (Http2::stream_priority_enabled) {
@@ -994,31 +999,31 @@ Http2ConnectionState::delete_stream(Http2Stream *stream)
 
   stream_list.remove(stream);
   stream->initiating_close();
-
-  if (http2_is_client_streamid(stream->get_id())) {
-    ink_assert(client_streams_in_count > 0);
-    --client_streams_in_count;
-  } else {
-    ink_assert(client_streams_out_count > 0);
-    --client_streams_out_count;
-  }
-
-  if (client_streams_in_count == 0 && client_streams_out_count == 0 && ua_session) {
-    ua_session->get_netvc()->add_to_keep_alive_queue();
-    ua_session->get_netvc()->cancel_active_timeout();
-  }
 }
 
 void
 Http2ConnectionState::release_stream(Http2Stream *stream)
 {
+  // Update stream counts
   if (stream) {
     --total_client_streams_count;
+    if (http2_is_client_streamid(stream->get_id())) {
+      ink_assert(client_streams_in_count > 0);
+      --client_streams_in_count;
+    } else {
+      ink_assert(client_streams_out_count > 0);
+      --client_streams_out_count;
+    }
+    stream_list.remove(stream);
   }
 
   // If the number of clients is 0, then mark the connection as inactive
   if (total_client_streams_count == 0 && ua_session) {
     ua_session->clear_session_active();
+    if (ua_session->get_netvc()) {
+      ua_session->get_netvc()->add_to_keep_alive_queue();
+      ua_session->get_netvc()->cancel_active_timeout();
+    }
   }
 
   if (ua_session && fini_received && total_client_streams_count == 0) {
@@ -1172,7 +1177,11 @@ Http2ConnectionState::send_a_data_frame(Http2Stream *stream, size_t &payload_len
 void
 Http2ConnectionState::send_data_frames(Http2Stream *stream)
 {
-  if (stream->get_state() == HTTP2_STREAM_STATE_CLOSED || stream->get_state() == HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL) {
+  // To follow RFC 7540 must not send more frames other than priority on
+  // a closed stream.  So we return without sending
+  if (stream->get_state() == HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL || stream->get_state() == HTTP2_STREAM_STATE_CLOSED) {
+    DebugSsn(this->ua_session, "http2_cs", "Shutdown half closed local stream %d", stream->get_id());
+    this->delete_stream(stream);
     return;
   }
 
diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc
index 84cb02e..8eb35fb 100644
--- a/proxy/http2/Http2Stream.cc
+++ b/proxy/http2/Http2Stream.cc
@@ -330,7 +330,7 @@ Http2Stream::do_io_close(int /* flags */)
       static_cast<Http2ClientSession *>(parent)->connection_state.send_data_frames(this);
     }
     // Check to see if the stream is in the closed state
-    ink_assert(get_state() == HTTP2_STREAM_STATE_CLOSED);
+    ink_assert(get_state() == HTTP2_STREAM_STATE_CLOSED || get_state() == HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE);
 
     clear_timers();
     clear_io_events();

-- 
To stop receiving notification emails like this one, please contact
['"commits@trafficserver.apache.org" <co...@trafficserver.apache.org>'].