فهرست منبع

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)
 	}