Procházet zdrojové kódy

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.
Yicheng Qin před 11 roky
rodič
revize
0814966ca2
2 změnil soubory, kde provedl 33 přidání a 1 odebrání
  1. 5 1
      etcdserver/raft.go
  2. 28 0
      etcdserver/raft_test.go

+ 5 - 1
etcdserver/raft.go

@@ -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)

+ 28 - 0
etcdserver/raft_test.go

@@ -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")
+	}
+}