Skip to content

Commit 3de7e33

Browse files
mfateevyycptt
authored andcommitted
Selector bug on receiving on closed channel (#846)
1 parent ac92fcf commit 3de7e33

File tree

2 files changed

+47
-1
lines changed

2 files changed

+47
-1
lines changed

internal/internal_coroutines_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,48 @@ func TestBlockingSelectAsyncSend(t *testing.T) {
358358
require.EqualValues(t, expected, history)
359359
}
360360

361+
func TestSelectOnClosedChannel(t *testing.T) {
362+
var history []string
363+
d, _ := newDispatcher(createRootTestContext(), func(ctx Context) {
364+
c := NewBufferedChannel(ctx, 1)
365+
c.Send(ctx, 5)
366+
c.Close()
367+
368+
selector := NewNamedSelector(ctx, "waiting for channel")
369+
370+
selector.AddReceive(c, func(f Channel, more bool) {
371+
var n int
372+
373+
if !more {
374+
history = append(history, "more from function is false")
375+
return
376+
}
377+
378+
more = f.Receive(ctx, &n)
379+
if !more {
380+
history = append(history, "more from receive is false")
381+
return
382+
}
383+
history = append(history, fmt.Sprintf("got message on channel: %v", n))
384+
})
385+
386+
selector.Select(ctx)
387+
selector.Select(ctx)
388+
selector.Select(ctx)
389+
selector.Select(ctx)
390+
})
391+
d.ExecuteUntilAllBlocked()
392+
require.True(t, d.IsDone(), strings.Join(history, "\n"))
393+
394+
expected := []string{
395+
"got message on channel: 5",
396+
"more from function is false",
397+
"more from function is false",
398+
"more from function is false",
399+
}
400+
require.EqualValues(t, expected, history)
401+
}
402+
361403
func TestBlockingSelectAsyncSend2(t *testing.T) {
362404
var history []string
363405
d, _ := newDispatcher(createRootTestContext(), func(ctx Context) {

internal/internal_workflow.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,11 @@ func (s *selectorImpl) Select(ctx Context) {
987987
// become ready they won't consume the value for this Select() call.
988988
readyBranch = func() {
989989
}
990-
c.recValue = &v
990+
// Avoid assigning pointer to nil interface which makes
991+
// c.RecValue != nil and breaks the nil check at the beginning of receiveAsyncImpl
992+
if more {
993+
c.recValue = &v
994+
}
991995
f(c, more)
992996
return
993997
}

0 commit comments

Comments
 (0)