@@ -1009,7 +1009,17 @@ func (c *Conn) queueRequest(opcode int32, req interface{}, res interface{}, recv
10091009
10101010func (c * Conn ) request (opcode int32 , req interface {}, res interface {}, recvFunc func (* request , * responseHeader , error )) (int64 , error ) {
10111011 r := <- c .queueRequest (opcode , req , res , recvFunc )
1012- return r .zxid , r .err
1012+ select {
1013+ case <- c .shouldQuit :
1014+ // queueRequest() can be racy, double-check for the race here and avoid
1015+ // a potential data-race. otherwise the client of this func may try to
1016+ // access `res` fields concurrently w/ the async response processor.
1017+ // NOTE: callers of this func should check for (at least) ErrConnectionClosed
1018+ // and avoid accessing fields of the response object if such error is present.
1019+ return - 1 , ErrConnectionClosed
1020+ default :
1021+ return r .zxid , r .err
1022+ }
10131023}
10141024
10151025func (c * Conn ) AddAuth (scheme string , auth []byte ) error {
@@ -1045,6 +1055,9 @@ func (c *Conn) Children(path string) ([]string, *Stat, error) {
10451055
10461056 res := & getChildren2Response {}
10471057 _ , err := c .request (opGetChildren2 , & getChildren2Request {Path : path , Watch : false }, res , nil )
1058+ if err == ErrConnectionClosed {
1059+ return nil , nil , err
1060+ }
10481061 return res .Children , & res .Stat , err
10491062}
10501063
@@ -1073,6 +1086,9 @@ func (c *Conn) Get(path string) ([]byte, *Stat, error) {
10731086
10741087 res := & getDataResponse {}
10751088 _ , err := c .request (opGetData , & getDataRequest {Path : path , Watch : false }, res , nil )
1089+ if err == ErrConnectionClosed {
1090+ return nil , nil , err
1091+ }
10761092 return res .Data , & res .Stat , err
10771093}
10781094
@@ -1102,6 +1118,9 @@ func (c *Conn) Set(path string, data []byte, version int32) (*Stat, error) {
11021118
11031119 res := & setDataResponse {}
11041120 _ , err := c .request (opSetData , & SetDataRequest {path , data , version }, res , nil )
1121+ if err == ErrConnectionClosed {
1122+ return nil , err
1123+ }
11051124 return & res .Stat , err
11061125}
11071126
@@ -1112,6 +1131,9 @@ func (c *Conn) Create(path string, data []byte, flags int32, acl []ACL) (string,
11121131
11131132 res := & createResponse {}
11141133 _ , err := c .request (opCreate , & CreateRequest {path , data , acl , flags }, res , nil )
1134+ if err == ErrConnectionClosed {
1135+ return "" , err
1136+ }
11151137 return res .Path , err
11161138}
11171139
@@ -1180,6 +1202,9 @@ func (c *Conn) Exists(path string) (bool, *Stat, error) {
11801202
11811203 res := & existsResponse {}
11821204 _ , err := c .request (opExists , & existsRequest {Path : path , Watch : false }, res , nil )
1205+ if err == ErrConnectionClosed {
1206+ return false , nil , err
1207+ }
11831208 exists := true
11841209 if err == ErrNoNode {
11851210 exists = false
@@ -1220,6 +1245,9 @@ func (c *Conn) GetACL(path string) ([]ACL, *Stat, error) {
12201245
12211246 res := & getAclResponse {}
12221247 _ , err := c .request (opGetAcl , & getAclRequest {Path : path }, res , nil )
1248+ if err == ErrConnectionClosed {
1249+ return nil , nil , err
1250+ }
12231251 return res .Acl , & res .Stat , err
12241252}
12251253func (c * Conn ) SetACL (path string , acl []ACL , version int32 ) (* Stat , error ) {
@@ -1229,6 +1257,9 @@ func (c *Conn) SetACL(path string, acl []ACL, version int32) (*Stat, error) {
12291257
12301258 res := & setAclResponse {}
12311259 _ , err := c .request (opSetAcl , & setAclRequest {Path : path , Acl : acl , Version : version }, res , nil )
1260+ if err == ErrConnectionClosed {
1261+ return nil , err
1262+ }
12321263 return & res .Stat , err
12331264}
12341265
@@ -1239,6 +1270,9 @@ func (c *Conn) Sync(path string) (string, error) {
12391270
12401271 res := & syncResponse {}
12411272 _ , err := c .request (opSync , & syncRequest {Path : path }, res , nil )
1273+ if err == ErrConnectionClosed {
1274+ return "" , err
1275+ }
12421276 return res .Path , err
12431277}
12441278
@@ -1274,6 +1308,9 @@ func (c *Conn) Multi(ops ...interface{}) ([]MultiResponse, error) {
12741308 }
12751309 res := & multiResponse {}
12761310 _ , err := c .request (opMulti , req , res , nil )
1311+ if err == ErrConnectionClosed {
1312+ return nil , err
1313+ }
12771314 mr := make ([]MultiResponse , len (res .Ops ))
12781315 for i , op := range res .Ops {
12791316 mr [i ] = MultiResponse {Stat : op .Stat , String : op .String , Error : op .Err .toError ()}
0 commit comments