diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 22:56:32 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2011-09-16 22:56:32 +0000 |
commit | 31aeabd3c51f798a7a3cbfab4bacbce983415ad8 (patch) | |
tree | 49f347d9773c306611f0d0b866ae9f0f9fa78147 | |
parent | e7f799cecc08fe69899b7f91e6e40744ce39b2eb (diff) | |
download | gcc-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.go | 8 | ||||
-rw-r--r-- | libgo/runtime/chan.goc | 4 | ||||
-rw-r--r-- | libgo/runtime/channel.h | 3 | ||||
-rw-r--r-- | libgo/runtime/go-rec-big.c | 5 | ||||
-rw-r--r-- | libgo/runtime/go-rec-nb-big.c | 7 | ||||
-rw-r--r-- | libgo/runtime/go-rec-nb-small.c | 8 | ||||
-rw-r--r-- | libgo/runtime/go-rec-small.c | 5 | ||||
-rw-r--r-- | libgo/runtime/go-reflect-chan.c | 15 | ||||
-rw-r--r-- | libgo/runtime/go-send-big.c | 5 | ||||
-rw-r--r-- | libgo/runtime/go-send-nb-big.c | 3 | ||||
-rw-r--r-- | libgo/runtime/go-send-nb-small.c | 3 | ||||
-rw-r--r-- | libgo/runtime/go-send-small.c | 5 |
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)); |