diff options
author | Peter Harris <git@peter.is-a-geek.org> | 2010-12-24 11:29:37 -0500 |
---|---|---|
committer | Peter Harris <git@peter.is-a-geek.org> | 2010-12-24 14:22:52 -0500 |
commit | a517f494442e70e79488c9f83c8c9856b453c82c (patch) | |
tree | 4462f93d5deb82054c31929ad9f6bc9fd5af2193 | |
parent | bc046920a1981b392a6ffc333fbaab7ef3ff8a72 (diff) |
Try harder to avoid deadlocks
By dropping the reply queue lock before actually trying to write,
we reduce the chances that the server won't read our blocking
socket due to us not reading events/replies/etc from earlier.
-rw-r--r-- | xgob.go | 20 |
1 files changed, 14 insertions, 6 deletions
@@ -45,6 +45,7 @@ type Connection struct { conn io.ReadWriteCloser reply map[uint64]chan interface {} replyMutex sync.Mutex + writeMutex sync.Mutex lastRequestWritten uint64 lastSequenceRead uint64 } @@ -257,6 +258,14 @@ func (c *Connection) fullSeq(seq uint16) uint64 { return fs } +func (c *Connection) registerReply (reply chan interface{}) { + c.replyMutex.Lock() + defer c.replyMutex.Unlock() + + c.lastRequestWritten++ + c.reply[c.lastRequestWritten] = reply +} + func (c *Connection) postReply (seq uint64, reply interface{}) { c.replyMutex.Lock() defer c.replyMutex.Unlock() @@ -350,19 +359,18 @@ func (c *Connection) Disconnect () { } func (c *Connection) WriteMultiRequest (req []byte, expected int) chan interface{} { - rv := make(chan interface {}, expected) - if c == nil || c.conn == nil { return rv } - c.replyMutex.Lock() - defer c.replyMutex.Unlock() + rv := make(chan interface {}, expected) - c.lastRequestWritten++ - c.reply[c.lastRequestWritten] = rv + c.writeMutex.Lock() + defer c.writeMutex.Unlock() + c.registerReply(rv) c.conn.Write(req) + return rv } |