瀏覽代碼

conn: ensure that call.framer is not nil

If a connection is closed then call to closeWithError will send
the error to the callers resp channel, which the caller in exec
will unblock, release the stream which will set the framer to nil.
Then if the response for that stream comes back from Cassandra into
recv() then the call.framer will be nil and will panic.

Instead of always releasing the stream when getting a reponse from
the channel only do it if there is no error.

Updates #439
Chris Bannister 10 年之前
父節點
當前提交
8819158121
共有 1 個文件被更改,包括 8 次插入5 次删除
  1. 8 5
      conn.go

+ 8 - 5
conn.go

@@ -444,11 +444,6 @@ func (c *Conn) exec(req frameWriter, tracer Tracer) (frame, error) {
 
 	select {
 	case err := <-call.resp:
-		// dont release the stream if detect a timeout as another request can reuse
-		// that stream and get a response for the old request, which we have no
-		// easy way of detecting.
-		defer c.releaseStream(stream)
-
 		if err != nil {
 			return nil, err
 		}
@@ -460,6 +455,14 @@ func (c *Conn) exec(req frameWriter, tracer Tracer) (frame, error) {
 		return nil, ErrConnectionClosed
 	}
 
+	// dont release the stream if detect a timeout as another request can reuse
+	// that stream and get a response for the old request, which we have no
+	// easy way of detecting.
+	//
+	// Ensure that the stream is not released if there are potentially outstanding
+	// requests on the stream to prevent nil pointer dereferences in recv().
+	defer c.releaseStream(stream)
+
 	if v := framer.header.version.version(); v != c.version {
 		return nil, NewErrProtocol("unexpected protocol version in response: got %d expected %d", v, c.version)
 	}