aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 22:56:32 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 22:56:32 +0000
commit31aeabd3c51f798a7a3cbfab4bacbce983415ad8 (patch)
tree49f347d9773c306611f0d0b866ae9f0f9fa78147
parente7f799cecc08fe69899b7f91e6e40744ce39b2eb (diff)
downloadgcc-31aeabd3c51f798a7a3cbfab4bacbce983415ad8.zip
gcc-31aeabd3c51f798a7a3cbfab4bacbce983415ad8.tar.gz
gcc-31aeabd3c51f798a7a3cbfab4bacbce983415ad8.tar.bz2
Block forever on send/receive to/from nil channel.
From-SVN: r178920
-rw-r--r--gcc/testsuite/go.test/test/chan/select3.go8
-rw-r--r--libgo/runtime/chan.goc4
-rw-r--r--libgo/runtime/channel.h3
-rw-r--r--libgo/runtime/go-rec-big.c5
-rw-r--r--libgo/runtime/go-rec-nb-big.c7
-rw-r--r--libgo/runtime/go-rec-nb-small.c8
-rw-r--r--libgo/runtime/go-rec-small.c5
-rw-r--r--libgo/runtime/go-reflect-chan.c15
-rw-r--r--libgo/runtime/go-send-big.c5
-rw-r--r--libgo/runtime/go-send-nb-big.c3
-rw-r--r--libgo/runtime/go-send-nb-small.c3
-rw-r--r--libgo/runtime/go-send-small.c5
12 files changed, 51 insertions, 20 deletions
diff --git a/gcc/testsuite/go.test/test/chan/select3.go b/gcc/testsuite/go.test/test/chan/select3.go
index b4e8f8e..d919de3 100644
--- a/gcc/testsuite/go.test/test/chan/select3.go
+++ b/gcc/testsuite/go.test/test/chan/select3.go
@@ -58,15 +58,15 @@ func main() {
closedch := make(chan int)
close(closedch)
- // sending/receiving from a nil channel outside a select panics
- testPanic(always, func() {
+ // sending/receiving from a nil channel blocks
+ testBlock(always, func() {
nilch <- 7
})
- testPanic(always, func() {
+ testBlock(always, func() {
<-nilch
})
- // sending/receiving from a nil channel inside a select never panics
+ // sending/receiving from a nil channel inside a select is never selected
testPanic(never, func() {
select {
case nilch <- 7:
diff --git a/libgo/runtime/chan.goc b/libgo/runtime/chan.goc
index acfff85..c3cc3e3 100644
--- a/libgo/runtime/chan.goc
+++ b/libgo/runtime/chan.goc
@@ -6,6 +6,8 @@ package runtime
#include "config.h"
#include "channel.h"
+#define nil NULL
+
typedef _Bool bool;
typedef unsigned char byte;
typedef struct __go_channel chan;
@@ -13,7 +15,7 @@ typedef struct __go_channel chan;
/* Do a channel receive with closed status. */
func chanrecv2(c *chan, val *byte) (received bool) {
- uintptr_t element_size = c->element_type->__size;
+ uintptr_t element_size = c == nil ? 0 : c->element_type->__size;
if (element_size > 8) {
return __go_receive_big(c, val, 0);
} else {
diff --git a/libgo/runtime/channel.h b/libgo/runtime/channel.h
index d4f1632..9176c68 100644
--- a/libgo/runtime/channel.h
+++ b/libgo/runtime/channel.h
@@ -147,3 +147,6 @@ extern void __go_builtin_close (struct __go_channel *);
extern int __go_chan_len (struct __go_channel *);
extern int __go_chan_cap (struct __go_channel *);
+
+extern uintptr_t __go_select (uintptr_t, _Bool, struct __go_channel **,
+ _Bool *);
diff --git a/libgo/runtime/go-rec-big.c b/libgo/runtime/go-rec-big.c
index 580ccb0..d45e90a 100644
--- a/libgo/runtime/go-rec-big.c
+++ b/libgo/runtime/go-rec-big.c
@@ -20,7 +20,10 @@ __go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
size_t offset;
if (channel == NULL)
- __go_panic_msg ("receive from nil channel");
+ {
+ /* Block forever. */
+ __go_select (0, 0, NULL, NULL);
+ }
element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
diff --git a/libgo/runtime/go-rec-nb-big.c b/libgo/runtime/go-rec-nb-big.c
index 8c315b1..659ea1d 100644
--- a/libgo/runtime/go-rec-nb-big.c
+++ b/libgo/runtime/go-rec-nb-big.c
@@ -18,6 +18,13 @@ __go_receive_nonblocking_big (struct __go_channel* channel, void *val,
size_t alloc_size;
size_t offset;
+ if (channel == NULL)
+ {
+ if (closed != NULL)
+ *closed = 0;
+ return 0;
+ }
+
element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
diff --git a/libgo/runtime/go-rec-nb-small.c b/libgo/runtime/go-rec-nb-small.c
index eb0a25e..0543920 100644
--- a/libgo/runtime/go-rec-nb-small.c
+++ b/libgo/runtime/go-rec-nb-small.c
@@ -97,6 +97,14 @@ __go_receive_nonblocking_small (struct __go_channel *channel)
uintptr_t element_size;
struct __go_receive_nonblocking_small ret;
+ if (channel == NULL)
+ {
+ ret.__val = 0;
+ ret.__success = 0;
+ ret.__closed = 0;
+ return ret;
+ }
+
element_size = channel->element_type->__size;
__go_assert (element_size <= sizeof (uint64_t));
diff --git a/libgo/runtime/go-rec-small.c b/libgo/runtime/go-rec-small.c
index 946a18c..d947632 100644
--- a/libgo/runtime/go-rec-small.c
+++ b/libgo/runtime/go-rec-small.c
@@ -270,7 +270,10 @@ __go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
uint64_t ret;
if (channel == NULL)
- __go_panic_msg ("receive from nil channel");
+ {
+ /* Block forever. */
+ __go_select (0, 0, NULL, NULL);
+ }
element_size = channel->element_type->__size;
__go_assert (element_size <= sizeof (uint64_t));
diff --git a/libgo/runtime/go-reflect-chan.c b/libgo/runtime/go-reflect-chan.c
index e8b4366..6f6693b 100644
--- a/libgo/runtime/go-reflect-chan.c
+++ b/libgo/runtime/go-reflect-chan.c
@@ -45,18 +45,13 @@ chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i,
void *pv;
__go_assert (ct->__common.__code == GO_CHAN);
- __go_assert (__go_type_descriptors_equal (ct->__element_type,
- channel->element_type));
- if (channel == NULL)
- __go_panic_msg ("send to nil channel");
-
- if (__go_is_pointer_type (channel->element_type))
+ if (__go_is_pointer_type (ct->__element_type))
pv = &val_i;
else
pv = (void *) val_i;
- element_size = channel->element_type->__size;
+ element_size = ct->__element_type->__size;
if (element_size <= sizeof (uint64_t))
{
union
@@ -112,12 +107,10 @@ chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb)
struct chanrecv_ret ret;
__go_assert (ct->__common.__code == GO_CHAN);
- __go_assert (__go_type_descriptors_equal (ct->__element_type,
- channel->element_type));
- element_size = channel->element_type->__size;
+ element_size = ct->__element_type->__size;
- if (__go_is_pointer_type (channel->element_type))
+ if (__go_is_pointer_type (ct->__element_type))
pv = &ret.val;
else
{
diff --git a/libgo/runtime/go-send-big.c b/libgo/runtime/go-send-big.c
index 0b4aa04..61d4a0f 100644
--- a/libgo/runtime/go-send-big.c
+++ b/libgo/runtime/go-send-big.c
@@ -17,7 +17,10 @@ __go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
size_t offset;
if (channel == NULL)
- __go_panic_msg ("send to nil channel");
+ {
+ // Block forever.
+ __go_select (0, 0, NULL, NULL);
+ }
element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
diff --git a/libgo/runtime/go-send-nb-big.c b/libgo/runtime/go-send-nb-big.c
index 1274859..e039874 100644
--- a/libgo/runtime/go-send-nb-big.c
+++ b/libgo/runtime/go-send-nb-big.c
@@ -15,6 +15,9 @@ __go_send_nonblocking_big (struct __go_channel* channel, const void *val)
size_t alloc_size;
size_t offset;
+ if (channel == NULL)
+ return 0;
+
element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
diff --git a/libgo/runtime/go-send-nb-small.c b/libgo/runtime/go-send-nb-small.c
index 0a25ba3..51914db 100644
--- a/libgo/runtime/go-send-nb-small.c
+++ b/libgo/runtime/go-send-nb-small.c
@@ -93,6 +93,9 @@ __go_send_nonblocking_acquire (struct __go_channel *channel)
_Bool
__go_send_nonblocking_small (struct __go_channel *channel, uint64_t val)
{
+ if (channel == NULL)
+ return 0;
+
__go_assert (channel->element_type->__size <= sizeof (uint64_t));
if (!__go_send_nonblocking_acquire (channel))
diff --git a/libgo/runtime/go-send-small.c b/libgo/runtime/go-send-small.c
index 8e21d36..25e3c82 100644
--- a/libgo/runtime/go-send-small.c
+++ b/libgo/runtime/go-send-small.c
@@ -145,7 +145,10 @@ void
__go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
{
if (channel == NULL)
- __go_panic_msg ("send to nil channel");
+ {
+ // Block forever.
+ __go_select (0, 0, NULL, NULL);
+ }
__go_assert (channel->element_type->__size <= sizeof (uint64_t));