@@ -545,8 +545,9 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
545545 c .timer .maybeRunChan (c )
546546 }
547547
548- // Fast path: check for failed non-blocking operation without acquiring the lock.
549- if ! block && empty (c ) {
548+ // Fast path: check for failed non-blocking operation and receiving on closed chan without
549+ // acquiring the lock.
550+ if empty (c ) {
550551 // After observing that the channel is not ready for receiving, we observe whether the
551552 // channel is closed.
552553 //
@@ -557,16 +558,18 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
557558 // separate critical sections under the same lock. This assumption fails when closing
558559 // an unbuffered channel with a blocked send, but that is an error condition anyway.
559560 if atomic .Load (& c .closed ) == 0 {
560- // Because a channel cannot be reopened, the later observation of the channel
561- // being not closed implies that it was also not closed at the moment of the
562- // first observation. We behave as if we observed the channel at that moment
563- // and report that the receive cannot proceed.
564- return
565- }
566- // The channel is irreversibly closed. Re-check whether the channel has any pending data
567- // to receive, which could have arrived between the empty and closed checks above.
568- // Sequential consistency is also required here, when racing with such a send.
569- if empty (c ) {
561+ if ! block {
562+ // Because a channel cannot be reopened, the later observation of the channel
563+ // being not closed implies that it was also not closed at the moment of the
564+ // first observation. We behave as if we observed the channel at that moment
565+ // and report that the receive cannot proceed.
566+ return
567+ }
568+ } else if empty (c ) {
569+ // The channel is irreversibly closed. Re-check whether the channel has any pending data
570+ // to receive, which could have arrived between the empty and closed checks above.
571+ // Sequential consistency is also required here, when racing with such a send.
572+
570573 // The channel is irreversibly closed and empty.
571574 if raceenabled {
572575 raceacquire (c .raceaddr ())
@@ -576,6 +579,7 @@ func chanrecv(c *hchan, ep unsafe.Pointer, block bool) (selected, received bool)
576579 }
577580 return true , false
578581 }
582+ // Fast path failed: this is not a closed chan or data in it. Lets get lock
579583 }
580584
581585 var t0 int64
0 commit comments