client/connection: fix deadlock on event dispatch

This commit is contained in:
StalkR 2015-03-31 23:49:40 +02:00
parent 0cac69d2ee
commit 1ebd4aa913
1 changed files with 5 additions and 1 deletions

View File

@ -207,6 +207,8 @@ func (conn *Conn) DisableStateTracking() {
// Per-connection state initialisation. // Per-connection state initialisation.
func (conn *Conn) initialise() { func (conn *Conn) initialise() {
conn.mu.Lock()
defer conn.mu.Unlock()
conn.io = nil conn.io = nil
conn.sock = nil conn.sock = nil
conn.die = make(chan struct{}) conn.die = make(chan struct{})
@ -404,8 +406,8 @@ func (conn *Conn) shutdown() {
// Guard against double-call of shutdown() if we get an error in send() // Guard against double-call of shutdown() if we get an error in send()
// as calling sock.Close() will cause recv() to receive EOF in readstring() // as calling sock.Close() will cause recv() to receive EOF in readstring()
conn.mu.Lock() conn.mu.Lock()
defer conn.mu.Unlock()
if !conn.connected { if !conn.connected {
conn.mu.Unlock()
return return
} }
logging.Info("irc.shutdown(): Disconnected from server.") logging.Info("irc.shutdown(): Disconnected from server.")
@ -415,6 +417,8 @@ func (conn *Conn) shutdown() {
conn.wg.Wait() conn.wg.Wait()
// Dispatch after closing connection but before reinit // Dispatch after closing connection but before reinit
// so event handlers can still access state information. // so event handlers can still access state information.
// Release lock before dispatch or we block handlers from accessing Me()
conn.mu.Unlock()
conn.dispatch(&Line{Cmd: DISCONNECTED, Time: time.Now()}) conn.dispatch(&Line{Cmd: DISCONNECTED, Time: time.Now()})
// reinit datastructures ready for next connection // reinit datastructures ready for next connection
conn.initialise() conn.initialise()