summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Harris <git@peter.is-a-geek.org>2010-12-24 11:29:37 -0500
committerPeter Harris <git@peter.is-a-geek.org>2010-12-24 14:22:52 -0500
commita517f494442e70e79488c9f83c8c9856b453c82c (patch)
tree4462f93d5deb82054c31929ad9f6bc9fd5af2193
parentbc046920a1981b392a6ffc333fbaab7ef3ff8a72 (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.go20
1 files changed, 14 insertions, 6 deletions
diff --git a/xgob.go b/xgob.go
index fc76de7..76dd579 100644
--- a/xgob.go
+++ b/xgob.go
@@ -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
}