etcdserver: stop raft loop when receiving stop signal

When it waits for apply to be done, it should stop the loop if it
receives stop signal.

This helps to print out panic information. Before this PR, if the panic
happens when server loop is applying entries, server loop will wait for
raft loop to stop forever.
This commit is contained in:
Yicheng Qin 2015-06-08 22:48:10 -07:00
parent 05b55d9d75
commit 0814966ca2
2 changed files with 33 additions and 1 deletions

View File

@ -161,7 +161,11 @@ func (r *raftNode) run() {
r.s.send(rd.Messages)
<-apply.done
select {
case <-apply.done:
case <-r.stopped:
return
}
r.Advance()
case <-syncC:
r.s.sync(defaultSyncTimeout)

View File

@ -18,9 +18,11 @@ import (
"encoding/json"
"reflect"
"testing"
"time"
"github.com/coreos/etcd/pkg/pbutil"
"github.com/coreos/etcd/pkg/types"
"github.com/coreos/etcd/raft"
"github.com/coreos/etcd/raft/raftpb"
)
@ -141,3 +143,29 @@ func TestCreateConfigChangeEnts(t *testing.T) {
}
}
}
func TestStopRaftWhenWaitingForApplyDone(t *testing.T) {
n := newReadyNode()
r := raftNode{
Node: n,
applyc: make(chan apply),
storage: &storageRecorder{},
raftStorage: raft.NewMemoryStorage(),
transport: &nopTransporter{},
}
r.s = &EtcdServer{r: r}
go r.run()
n.readyc <- raft.Ready{}
select {
case <-r.applyc:
case <-time.After(time.Second):
t.Fatalf("failed to receive apply struct")
}
r.stopped <- struct{}{}
select {
case <-r.done:
case <-time.After(time.Second):
t.Fatalf("failed to stop raft loop")
}
}