Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clientv3: process closed watcherStreams in watcherGrpcStream run loop #6487

Merged
merged 2 commits into from
Sep 21, 2016

Conversation

heyitsanthony
Copy link
Contributor

Fixes #6476

/cc @hongchaodeng

@@ -131,6 +131,8 @@ type watchGrpcStream struct {
donec chan struct{}
// errc transmits errors from grpc Recv to the watch stream reconn logic
errc chan error
// servec gets the watcherStream of a closed watcher
servec chan *watcherStream
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is it better to call this closedWatcherc?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

closingc?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

@xiang90
Copy link
Contributor

xiang90 commented Sep 21, 2016

LGTM.

One nit: can you write about when the race can happen (an example sequence)?

t.Fatal(err)
}

// several unique contexts for several unique streams
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5 instead of several?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't want to bake the constant into the comment

idx := rand.Intn(len(ctxs))
ctx, cancel := context.WithCancel(ctxs[idx])
ctxc[idx] <- struct{}{}
ch := cli.Watch(ctx, "abc", clientv3.WithRev(1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make key "abc" a const in this test?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when did we start writing tests like that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the bad thing about this "abc" key is that the put req is not close to the watch req. reader might lose context. changing it to putkey or something is easier for the reader.

@xiang90
Copy link
Contributor

xiang90 commented Sep 21, 2016

The CI failure might be related?

Copy link
Contributor

@hongchaodeng hongchaodeng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @heyitsanthony for putting up the change.

idx := rand.Intn(len(ctxs))
ctx, cancel := context.WithCancel(ctxs[idx])
ctxc[idx] <- struct{}{}
ch := cli.Watch(ctx, "abc", clientv3.WithRev(1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change "ch" to "wch". Differentiate from existing var.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

@@ -759,3 +759,52 @@ func TestWatchCancelOnServer(t *testing.T) {
t.Fatalf("expected 0 watchers, got %q", watchers)
}
}

// TestWatchOverlapContextCancel checks watcher stream per-context accounting.
Copy link
Contributor

@hongchaodeng hongchaodeng Sep 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// ... checks watch context created in the same way, e.g. context.WithCancel(parentCtx), 
// should be managed and accounted separately and correctly during cancelling each other.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok reworked the comment.

if _, ok := <-ch; !ok {
t.Fatalf("unexpected closed channel")
}
// randomize how cancel overlaps with watch creation
Copy link
Contributor

@hongchaodeng hongchaodeng Sep 21, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this could happen without overlapping cancel calls?
If so, can we get rid of the "ctxc" thing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It could happen, but this synchronization is important to stress the teardown path. Otherwise, watchers will pile up on the streams instead of oscillating between 0, 1, and 2 watchers. I'll add a comment.

@@ -491,6 +497,11 @@ func (w *watchGrpcStream) run() {
cancelSet = make(map[int64]struct{})
case <-stopc:
return

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove empty line

Was racing with Watch() when closing the grpc stream on no watchers.

Fixes etcd-io#6476
@timothysc
Copy link

Should we cherry-pick this one?

@heyitsanthony
Copy link
Contributor Author

@timothysc yes, I think so. Tagged for backporting.

@heyitsanthony heyitsanthony deleted the watch-stress branch October 4, 2016 23:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

5 participants