mirror of
https://github.com/golang/go
synced 2024-11-21 19:14:44 -07:00
Fix a deadlock bug in the rpc client. The panic will trigger
regularly when client connections are flaky (probably another issue). (credits to jussi@tinkercad.com for finding the issue) R=rsc, r CC=golang-dev, jussi https://golang.org/cl/2831042
This commit is contained in:
parent
59315fbfb5
commit
95b40f6ca1
@ -69,12 +69,12 @@ func (client *Client) send(c *Call) {
|
||||
// Encode and send the request.
|
||||
request := new(Request)
|
||||
client.sending.Lock()
|
||||
defer client.sending.Unlock()
|
||||
request.Seq = c.seq
|
||||
request.ServiceMethod = c.ServiceMethod
|
||||
if err := client.codec.WriteRequest(request, c.Args); err != nil {
|
||||
panic("rpc: client encode error: " + err.String())
|
||||
}
|
||||
client.sending.Unlock()
|
||||
}
|
||||
|
||||
func (client *Client) input() {
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -332,3 +333,52 @@ func TestRegistrationError(t *testing.T) {
|
||||
t.Errorf("expected error registering ReplyNotPublic")
|
||||
}
|
||||
}
|
||||
|
||||
type WriteFailCodec int
|
||||
|
||||
func (WriteFailCodec) WriteRequest(*Request, interface{}) os.Error {
|
||||
// the panic caused by this error used to not unlock a lock.
|
||||
return os.NewError("fail")
|
||||
}
|
||||
|
||||
func (WriteFailCodec) ReadResponseHeader(*Response) os.Error {
|
||||
time.Sleep(60e9)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (WriteFailCodec) ReadResponseBody(interface{}) os.Error {
|
||||
time.Sleep(60e9)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func (WriteFailCodec) Close() os.Error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestSendDeadlock(t *testing.T) {
|
||||
client := NewClientWithCodec(WriteFailCodec(0))
|
||||
|
||||
done := make(chan bool)
|
||||
go func() {
|
||||
testSendDeadlock(client)
|
||||
testSendDeadlock(client)
|
||||
done <- true
|
||||
}()
|
||||
for i := 0; i < 50; i++ {
|
||||
time.Sleep(100 * 1e6)
|
||||
_, ok := <-done
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Fatal("deadlock")
|
||||
}
|
||||
|
||||
func testSendDeadlock(client *Client) {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
args := &Args{7, 8}
|
||||
reply := new(Reply)
|
||||
client.Call("Arith.Add", args, reply)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user