Add mutex for connect/disconnect locking.

This commit is contained in:
Alex Bramley 2013-02-18 01:36:52 +00:00
parent a323372a0b
commit 12bcc94eeb
1 changed files with 20 additions and 11 deletions

View File

@ -8,11 +8,14 @@ import (
"github.com/fluffle/golog/logging" "github.com/fluffle/golog/logging"
"net" "net"
"strings" "strings"
"sync"
"time" "time"
) )
// An IRC connection is represented by this struct. // An IRC connection is represented by this struct.
type Conn struct { type Conn struct {
// For preventing races on (dis)connect.
mu sync.Mutex
// Contains parameters that people can tweak to change client behaviour. // Contains parameters that people can tweak to change client behaviour.
cfg *Config cfg *Config
@ -164,6 +167,9 @@ func (conn *Conn) ConnectTo(host string, pass ...string) error {
} }
func (conn *Conn) Connect() error { func (conn *Conn) Connect() error {
conn.mu.Lock()
defer conn.mu.Unlock()
if conn.cfg.Server == "" { if conn.cfg.Server == "" {
return fmt.Errorf("irc.Connect(): cfg.Server must be non-empty") return fmt.Errorf("irc.Connect(): cfg.Server must be non-empty")
} }
@ -326,10 +332,14 @@ func (conn *Conn) rateLimit(chars int) time.Duration {
func (conn *Conn) shutdown() { 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()
if conn.Connected { conn.mu.Lock()
defer conn.mu.Unlock()
if !conn.connected {
return
}
logging.Info("irc.shutdown(): Disconnected from server.") logging.Info("irc.shutdown(): Disconnected from server.")
conn.dispatch(&Line{Cmd: "disconnected"}) conn.dispatch(&Line{Cmd: DISCONNECTED})
conn.Connected = false conn.connected = false
conn.sock.Close() conn.sock.Close()
conn.cSend <- true conn.cSend <- true
conn.cLoop <- true conn.cLoop <- true
@ -337,7 +347,6 @@ func (conn *Conn) shutdown() {
// reinit datastructures ready for next connection // reinit datastructures ready for next connection
// do this here rather than after runLoop()'s for due to race // do this here rather than after runLoop()'s for due to race
conn.initialise() conn.initialise()
}
} }
// Dumps a load of information about the current state of the connection to a // Dumps a load of information about the current state of the connection to a