// 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() {
"strings"
"sync"
"testing"
+ "time"
)
var (
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)
+}