Commit 4bfebf0a authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #32907 from hongchaodeng/etcd_fix

Automatic merge from submit-queue etcd watcher: centralize error handling We should centralize error handling in watcher in run(). Otherwise this could silently return. Also we don't need the grpc code checking anymore. It's fixed.
parents a089791f 5a4a095e
...@@ -31,8 +31,6 @@ import ( ...@@ -31,8 +31,6 @@ import (
etcdrpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes" etcdrpc "github.com/coreos/etcd/etcdserver/api/v3rpc/rpctypes"
"github.com/golang/glog" "github.com/golang/glog"
"golang.org/x/net/context" "golang.org/x/net/context"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
) )
const ( const (
...@@ -109,6 +107,10 @@ func (wc *watchChan) run() { ...@@ -109,6 +107,10 @@ func (wc *watchChan) run() {
select { select {
case err := <-wc.errChan: case err := <-wc.errChan:
if err == context.Canceled {
wc.cancel() // just in case
break
}
errResult := parseError(err) errResult := parseError(err)
if errResult != nil { if errResult != nil {
// error result is guaranteed to be received by user before closing ResultChan. // error result is guaranteed to be received by user before closing ResultChan.
...@@ -294,12 +296,6 @@ func parseError(err error) *watch.Event { ...@@ -294,12 +296,6 @@ func parseError(err error) *watch.Event {
} }
func (wc *watchChan) sendError(err error) { func (wc *watchChan) sendError(err error) {
// Context.canceled is an expected behavior.
// We should just stop all goroutines in watchChan without returning error.
// TODO: etcd client should return context.Canceled instead of grpc specific error.
if grpc.Code(err) == codes.Canceled || err == context.Canceled {
return
}
select { select {
case wc.errChan <- err: case wc.errChan <- err:
case <-wc.ctx.Done(): case <-wc.ctx.Done():
......
...@@ -196,17 +196,20 @@ func TestWatchContextCancel(t *testing.T) { ...@@ -196,17 +196,20 @@ func TestWatchContextCancel(t *testing.T) {
defer cluster.Terminate(t) defer cluster.Terminate(t)
canceledCtx, cancel := context.WithCancel(ctx) canceledCtx, cancel := context.WithCancel(ctx)
cancel() cancel()
w := store.watcher.createWatchChan(canceledCtx, "/abc", 0, false, storage.Everything) // When we watch with a canceled context, we should detect that it's context canceled.
// When we do a client.Get with a canceled context, it will return error. // We won't take it as error and also close the watcher.
// Nonetheless, when we try to send it over internal errChan, we should detect w, err := store.watcher.Watch(canceledCtx, "/abc", 0, false, storage.Everything)
// it's context canceled and not send it. if err != nil {
err := w.sync() t.Fatal(err)
w.ctx = ctx }
w.sendError(err)
select { select {
case err := <-w.errChan: case _, ok := <-w.ResultChan():
t.Errorf("cancelling context shouldn't return any error. Err: %v", err) if ok {
default: t.Error("ResultChan() should be closed")
}
case <-time.After(wait.ForeverTestTimeout):
t.Errorf("timeout after %v", wait.ForeverTestTimeout)
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment