try to shutdown more safely so callbacks, etc don't try and use the read/write channels after they are closed

This commit is contained in:
Andrew Montgomery-Hurrell 2014-02-09 12:02:05 +00:00
parent 09ea5672e2
commit 0b6c954b52
2 changed files with 85 additions and 67 deletions

24
irc.go
View File

@ -23,6 +23,11 @@ func (irc *Connection) readLoop() {
br := bufio.NewReaderSize(irc.socket, 512)
for {
select {
case <-irc.endread:
irc.readerExit <- true
return
default:
// Set a read deadline based on the combined timeout and ping frequency
// We should ALWAYS have received a response from the server within the timeout
// after our own pings
@ -77,15 +82,22 @@ func (irc *Connection) readLoop() {
irc.RunCallbacks(event)
}
}
irc.readerExit <- true
}
func (irc *Connection) writeLoop() {
for {
select {
case <-irc.endwrite:
irc.writerExit <- true
return
default:
b, ok := <-irc.pwrite
if !ok || b == "" || irc.socket == nil {
break
irc.writerExit <- true
return
}
if irc.Debug {
@ -103,7 +115,9 @@ func (irc *Connection) writeLoop() {
if err != nil {
irc.Error <- err
break
irc.writerExit <- true
return
}
}
}
irc.writerExit <- true
@ -206,9 +220,11 @@ func (irc *Connection) GetNick() string {
// Sends all buffered messages (if possible),
// stops all goroutines and then closes the socket.
func (irc *Connection) Disconnect() {
irc.endping <- true
irc.endwrite <- true
irc.endread <- true
close(irc.pwrite)
close(irc.pread)
irc.endping <- true
<-irc.readerExit
<-irc.writerExit
@ -267,6 +283,8 @@ func IRC(nick, user string) *Connection {
writerExit: make(chan bool),
pingerExit: make(chan bool),
endping: make(chan bool),
endread: make(chan bool),
endwrite: make(chan bool),
Version: VERSION,
KeepAlive: 4 * time.Minute,
Timeout: 1 * time.Minute,

View File

@ -26,7 +26,7 @@ type Connection struct {
netsock net.Conn
pread, pwrite chan string
readerExit, writerExit, pingerExit chan bool
endping chan bool
endping, endread, endwrite chan bool
nick string //The nickname we want.
nickcurrent string //The nickname we currently have.