]> Cypherpunks repositories - gostls13.git/commitdiff
gc: disallow close on receive-only channels
authorRuss Cox <rsc@golang.org>
Thu, 13 Oct 2011 20:58:04 +0000 (16:58 -0400)
committerRuss Cox <rsc@golang.org>
Thu, 13 Oct 2011 20:58:04 +0000 (16:58 -0400)
Fixes #2353.
Fixes #2246.

R=golang-dev, r, gri
CC=golang-dev
https://golang.org/cl/5282042

doc/go_spec.html
src/cmd/gc/typecheck.c
src/pkg/runtime/chan.c
test/chan/perm.go
test/closedchan.go

index 13f52996c4dcb5ccbdce21efe30e64f413581aa5..810df2c46a8c964223f6cc20b7f4857641c88b60 100644 (file)
@@ -4531,12 +4531,13 @@ BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .
 
 <p>
 For a channel <code>c</code>, the built-in function <code>close(c)</code>
-marks the channel as unable to accept more values through a send operation;
-sending to or closing a closed channel causes a <a href="#Run_time_panics">run-time panic</a>.
+records that no more values will be sent on the channel.
+It is an error if <code>c</code> is a receive-only channel.
+Sending to or closing a closed channel causes a <a href="#Run_time_panics">run-time panic</a>.
+Closing the nil channel also causes a <a href="#Run_time_panics">run-time panic</a>.
 After calling <code>close</code>, 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 <a href="#Receive_operator">receive operation</a>
 returns a received value along with an indication of whether the channel is closed.
 </p>
index 052fc74dffc870e21c83ccca9cad4eaeb8c1089a..0b2e6f0ca603ba2fbfb343ff72cd76df56ffe2f3 100644 (file)
@@ -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;
 
index cc056f65f10f52b4ecddc6d3352b670b2e7ef147..475da233c1398b93c7e7a4e8f155946a57da3f73 100644 (file)
@@ -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();
 
index 038ff94e369b980baa7bed42b8fec65a9a52ee4e..af054450eabafbe67bc3f317e9d9b98afe567666 100644 (file)
@@ -48,4 +48,8 @@ func main() {
        case x := <-cs: // ERROR "receive"
                _ = x
        }
+       
+       close(c)
+       close(cs)
+       close(cr)  // ERROR "receive"
 }
index 95314b3345e4475e1ba6492ae2a667a91c9a775b..0dbe662d84f985b6821c5d5260bd988a5dbbceec 100644 (file)
@@ -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)
+       })
 }