Skip to content

Commit 2abb334

Browse files
authored
Merge pull request #18893 from ktalg/fix-comparing-ctx
fix runtime error: comparing uncomparable type
2 parents 978985d + 8176118 commit 2abb334

File tree

2 files changed

+39
-2
lines changed

2 files changed

+39
-2
lines changed

client/v3/lease.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,12 @@ func (l *lessor) Leases(ctx context.Context) (*LeaseLeasesResponse, error) {
264264
return nil, ContextError(ctx, err)
265265
}
266266

267+
// To identify the context passed to `KeepAlive`, a key/value pair is
268+
// attached to the context. The key is a `keepAliveCtxKey` object, and
269+
// the value is the pointer to the context object itself, ensuring
270+
// uniqueness as each context has a unique memory address.
271+
type keepAliveCtxKey struct{}
272+
267273
func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAliveResponse, error) {
268274
ch := make(chan *LeaseKeepAliveResponse, LeaseResponseChSize)
269275

@@ -278,6 +284,10 @@ func (l *lessor) KeepAlive(ctx context.Context, id LeaseID) (<-chan *LeaseKeepAl
278284
default:
279285
}
280286
ka, ok := l.keepAlives[id]
287+
288+
if ctx.Done() != nil {
289+
ctx = context.WithValue(ctx, keepAliveCtxKey{}, &ctx)
290+
}
281291
if !ok {
282292
// create fresh keep alive
283293
ka = &keepAlive{
@@ -348,7 +358,7 @@ func (l *lessor) keepAliveCtxCloser(ctx context.Context, id LeaseID, donec <-cha
348358

349359
// close channel and remove context if still associated with keep alive
350360
for i, c := range ka.ctxs {
351-
if c == ctx {
361+
if c.Value(keepAliveCtxKey{}) == ctx.Value(keepAliveCtxKey{}) {
352362
close(ka.chs[i])
353363
ka.ctxs = append(ka.ctxs[:i], ka.ctxs[i+1:]...)
354364
ka.chs = append(ka.chs[:i], ka.chs[i+1:]...)

tests/integration/clientv3/lease/lease_test.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,14 @@ func TestLeaseKeepAlive(t *testing.T) {
136136
t.Errorf("failed to create lease %v", err)
137137
}
138138

139-
rc, kerr := lapi.KeepAlive(context.Background(), resp.ID)
139+
type uncomparableCtx struct {
140+
context.Context
141+
_ func()
142+
}
143+
144+
ctx, cancel := context.WithCancel(context.Background())
145+
defer cancel()
146+
rc, kerr := lapi.KeepAlive(uncomparableCtx{Context: ctx}, resp.ID)
140147
if kerr != nil {
141148
t.Errorf("failed to keepalive lease %v", kerr)
142149
}
@@ -154,6 +161,26 @@ func TestLeaseKeepAlive(t *testing.T) {
154161
t.Errorf("ID = %x, want %x", kresp.ID, resp.ID)
155162
}
156163

164+
ctx2, cancel2 := context.WithCancel(context.Background())
165+
rc2, kerr2 := lapi.KeepAlive(uncomparableCtx{Context: ctx2}, resp.ID)
166+
if kerr2 != nil {
167+
t.Errorf("failed to keepalive lease %v", kerr2)
168+
}
169+
170+
cancel2()
171+
172+
_, ok = <-rc2
173+
if ok {
174+
t.Errorf("chan is not closed, want cancel stop keepalive")
175+
}
176+
177+
select {
178+
case <-rc:
179+
// cancel2() should not affect first keepalive
180+
t.Errorf("chan is closed, want keepalive continue")
181+
default:
182+
}
183+
157184
lapi.Close()
158185

159186
_, ok = <-rc

0 commit comments

Comments
 (0)