Commit f58ed4e6 authored by Russ Cox's avatar Russ Cox

gc: disallow close on receive-only channels

Fixes #2353.
Fixes #2246.

R=golang-dev, r, gri
CC=golang-dev
https://golang.org/cl/5282042
parent d65aaf24
...@@ -4531,12 +4531,13 @@ BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList . ...@@ -4531,12 +4531,13 @@ BuiltinArgs = Type [ "," ExpressionList ] | ExpressionList .
<p> <p>
For a channel <code>c</code>, the built-in function <code>close(c)</code> 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; records that no more values will be sent on the channel.
sending to or closing a closed channel causes a <a href="#Run_time_panics">run-time panic</a>. 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 After calling <code>close</code>, and after any previously
sent values have been received, receive operations will return sent values have been received, receive operations will return
the zero value for the channel's type without blocking. the zero value for the channel's type without blocking.
The multi-valued <a href="#Receive_operator">receive operation</a> The multi-valued <a href="#Receive_operator">receive operation</a>
returns a received value along with an indication of whether the channel is closed. returns a received value along with an indication of whether the channel is closed.
</p> </p>
......
...@@ -984,6 +984,10 @@ reswitch: ...@@ -984,6 +984,10 @@ reswitch:
yyerror("invalid operation: %#N (non-chan type %T)", n, t); yyerror("invalid operation: %#N (non-chan type %T)", n, t);
goto error; goto error;
} }
if(!(t->chan & Csend)) {
yyerror("invalid operation: %#N (cannot close receive-only channel)", n);
goto error;
}
ok |= Etop; ok |= Etop;
goto ret; goto ret;
......
...@@ -1052,6 +1052,9 @@ runtime·closechan(Hchan *c) ...@@ -1052,6 +1052,9 @@ runtime·closechan(Hchan *c)
SudoG *sg; SudoG *sg;
G* gp; G* gp;
if(c == nil)
runtime·panicstring("close of nil channel");
if(runtime·gcwaiting) if(runtime·gcwaiting)
runtime·gosched(); runtime·gosched();
......
...@@ -48,4 +48,8 @@ func main() { ...@@ -48,4 +48,8 @@ func main() {
case x := <-cs: // ERROR "receive" case x := <-cs: // ERROR "receive"
_ = x _ = x
} }
close(c)
close(cs)
close(cr) // ERROR "receive"
} }
...@@ -327,4 +327,15 @@ func main() { ...@@ -327,4 +327,15 @@ func main() {
testclosed(mk(closedasync())) testclosed(mk(closedasync()))
} }
} }
var ch chan int
shouldPanic(func() {
close(ch)
})
ch = make(chan int)
close(ch)
shouldPanic(func() {
close(ch)
})
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment