RPC stream client/server mutex fix (#884)

* Unlock RPC client while actually receiving a message

As receiving a message might block for a long time, unblocking the client allows to let it send messages in the meanwhile without using 'tricks'

* Unlock RPC server while actually receiving a message

As receiving a message might block for a long time, unblocking the client allows to let it send messages in the meanwhile without using 'tricks'

* Protect Close() against race conditions

* Concurrency and Sequence tests
This commit is contained in:
Maarten Bezemer
2020-01-12 10:13:14 +01:00
committed by Asim Aslam
parent fa5b3ee9d9
commit 50b20413d3
3 changed files with 159 additions and 8 deletions

View File

@@ -83,7 +83,10 @@ func (r *rpcStream) Recv(msg interface{}) error {
var resp codec.Message
if err := r.codec.ReadHeader(&resp, codec.Response); err != nil {
r.Unlock()
err := r.codec.ReadHeader(&resp, codec.Response)
r.Lock()
if err != nil {
if err == io.EOF && !r.isClosed() {
r.err = io.ErrUnexpectedEOF
return io.ErrUnexpectedEOF
@@ -102,11 +105,17 @@ func (r *rpcStream) Recv(msg interface{}) error {
} else {
r.err = io.EOF
}
if err := r.codec.ReadBody(nil); err != nil {
r.Unlock()
err = r.codec.ReadBody(nil)
r.Lock()
if err != nil {
r.err = err
}
default:
if err := r.codec.ReadBody(msg); err != nil {
r.Unlock()
err = r.codec.ReadBody(msg)
r.Lock()
if err != nil {
r.err = err
}
}
@@ -121,11 +130,15 @@ func (r *rpcStream) Error() error {
}
func (r *rpcStream) Close() error {
r.RLock()
select {
case <-r.closed:
r.RUnlock()
return nil
default:
close(r.closed)
r.RUnlock()
// send the end of stream message
if r.sendEOS {