1
0
mirror of https://github.com/golang/go synced 2024-11-22 00:24:41 -07:00

gc: disallow close on receive-only channels

Fixes #2353.
Fixes #2246.

R=golang-dev, r, gri
CC=golang-dev
https://golang.org/cl/5282042
This commit is contained in:
Russ Cox 2011-10-13 16:58:04 -04:00
parent d65aaf24a6
commit f58ed4e641
5 changed files with 26 additions and 3 deletions

View File

@ -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>

View File

@ -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;

View File

@ -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();

View File

@ -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"
} }

View File

@ -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)
})
} }