diff --git a/doc/go_spec.html b/doc/go_spec.html index 13f52996c4..810df2c46a 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -4531,12 +4531,13 @@ BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .

For a channel c, the built-in function close(c) -marks the channel as unable to accept more values through a send operation; -sending to or closing a closed channel causes a run-time panic. +records that no more values will be sent on the channel. +It is an error if c is a receive-only channel. +Sending to or closing a closed channel causes a run-time panic. +Closing the nil channel also causes a run-time panic. After calling close, and after any previously sent values have been received, receive operations will return the zero value for the channel's type without blocking. - The multi-valued receive operation returns a received value along with an indication of whether the channel is closed.

diff --git a/src/cmd/gc/typecheck.c b/src/cmd/gc/typecheck.c index 052fc74dff..0b2e6f0ca6 100644 --- a/src/cmd/gc/typecheck.c +++ b/src/cmd/gc/typecheck.c @@ -984,6 +984,10 @@ reswitch: yyerror("invalid operation: %#N (non-chan type %T)", n, t); goto error; } + if(!(t->chan & Csend)) { + yyerror("invalid operation: %#N (cannot close receive-only channel)", n); + goto error; + } ok |= Etop; goto ret; diff --git a/src/pkg/runtime/chan.c b/src/pkg/runtime/chan.c index cc056f65f1..475da233c1 100644 --- a/src/pkg/runtime/chan.c +++ b/src/pkg/runtime/chan.c @@ -1052,6 +1052,9 @@ runtime·closechan(Hchan *c) SudoG *sg; G* gp; + if(c == nil) + runtime·panicstring("close of nil channel"); + if(runtime·gcwaiting) runtime·gosched(); diff --git a/test/chan/perm.go b/test/chan/perm.go index 038ff94e36..af054450ea 100644 --- a/test/chan/perm.go +++ b/test/chan/perm.go @@ -48,4 +48,8 @@ func main() { case x := <-cs: // ERROR "receive" _ = x } + + close(c) + close(cs) + close(cr) // ERROR "receive" } diff --git a/test/closedchan.go b/test/closedchan.go index 95314b3345..0dbe662d84 100644 --- a/test/closedchan.go +++ b/test/closedchan.go @@ -327,4 +327,15 @@ func main() { testclosed(mk(closedasync())) } } + + var ch chan int + shouldPanic(func() { + close(ch) + }) + + ch = make(chan int) + close(ch) + shouldPanic(func() { + close(ch) + }) }