From 17e5216144af2d0e404e13537d3ac5b7cd9dbc4c Mon Sep 17 00:00:00 2001 From: Alex Bramley Date: Sat, 19 Dec 2009 19:00:27 +0000 Subject: [PATCH] fix race and reinit conn.Me on disconnect * due to the blocking nature of channel reads, by the time the runLoop() for loop exits in that goroutine, we might well be half-way through reconnecting to the server -- a bad time to run conn.initialise(). move the call to initialise() into shutdown() to ensure it happens in a timely manner. * On a related note, conn.Me was retaining old channel objects in it's Channels map. All other references to nicks and channels are erased in conn.initialise(), but as we keep a seperate reference to our Nick object in conn.Me, we need to reinit that at the same time. --- irc/connection.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/irc/connection.go b/irc/connection.go index 102041a..c3f71dc 100644 --- a/irc/connection.go +++ b/irc/connection.go @@ -69,6 +69,12 @@ func (conn *Conn) initialise() { conn.Err = make(chan os.Error, 4) conn.io = nil conn.sock = nil + + // if this is being called because we are reconnecting, conn.Me + // will still have all the old channels referenced -- nuke them! + if conn.Me != nil { + conn.Me = conn.NewNick(conn.Me.Nick, conn.Me.Ident, conn.Me.Name, "") + } } // Connect the IRC connection object to "host[:port]" which should be either @@ -200,10 +206,6 @@ func (conn *Conn) runLoop() { for line := range conn.in { conn.dispatchEvent(line) } - // if we fall off the end here due to shutdown, - // reinit everything once the runloop is done - // so that Connect() can be called again. - conn.initialise() } func (conn *Conn) shutdown() { @@ -212,6 +214,9 @@ func (conn *Conn) shutdown() { close(conn.Err) conn.connected = false conn.sock.Close() + // reinit datastructures ready for next connection + // do this here rather than after runLoop()'s for due to race + conn.initialise() } // Dumps a load of information about the current state of the connection to a