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

View File

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