etcdserver: stop raft node goroutine before stop server

Stop raftNode goroutine before stopping server goroutine, so
server.Stop does stop all underlying stuffs elegantly now. This fixes
the problem that previous-round lock on WAL may not be released when
etcd is restarted.
This commit is contained in:
Yicheng Qin 2015-04-01 11:01:22 -07:00
parent 2c7a8c2216
commit 9e5743c816
2 changed files with 14 additions and 4 deletions

View File

@ -101,9 +101,15 @@ type raftNode struct {
index uint64
term uint64
lead uint64
stopped chan struct{}
done chan struct{}
}
func (r *raftNode) run() {
r.stopped = make(chan struct{})
r.done = make(chan struct{})
var syncC <-chan time.Time
defer r.stop()
@ -134,7 +140,7 @@ func (r *raftNode) run() {
select {
case r.applyc <- apply:
case <-r.s.done:
case <-r.stopped:
return
}
@ -156,7 +162,7 @@ func (r *raftNode) run() {
r.Advance()
case <-syncC:
r.s.sync(defaultSyncTimeout)
case <-r.s.done:
case <-r.stopped:
return
}
}
@ -172,6 +178,7 @@ func (r *raftNode) stop() {
if err := r.storage.Close(); err != nil {
log.Panicf("etcdraft: close storage error: %v", err)
}
close(r.done)
}
// for testing

View File

@ -341,7 +341,11 @@ func (s *EtcdServer) run() {
s.r.s = s
s.r.applyc = make(chan apply)
go s.r.run()
defer close(s.done)
defer func() {
s.r.stopped <- struct{}{}
<-s.r.done
close(s.done)
}()
var shouldstop bool
for {
@ -404,7 +408,6 @@ func (s *EtcdServer) run() {
return
}
}
// TODO: wait for the stop of raft node routine?
}
// Stop stops the server gracefully, and shuts down the running goroutine.