Commit 31aeabd3 by Ian Lance Taylor

Block forever on send/receive to/from nil channel.

From-SVN: r178920
parent e7f799ce
...@@ -58,15 +58,15 @@ func main() { ...@@ -58,15 +58,15 @@ func main() {
closedch := make(chan int) closedch := make(chan int)
close(closedch) close(closedch)
// sending/receiving from a nil channel outside a select panics // sending/receiving from a nil channel blocks
testPanic(always, func() { testBlock(always, func() {
nilch <- 7 nilch <- 7
}) })
testPanic(always, func() { testBlock(always, func() {
<-nilch <-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() { testPanic(never, func() {
select { select {
case nilch <- 7: case nilch <- 7:
......
...@@ -6,6 +6,8 @@ package runtime ...@@ -6,6 +6,8 @@ package runtime
#include "config.h" #include "config.h"
#include "channel.h" #include "channel.h"
#define nil NULL
typedef _Bool bool; typedef _Bool bool;
typedef unsigned char byte; typedef unsigned char byte;
typedef struct __go_channel chan; typedef struct __go_channel chan;
...@@ -13,7 +15,7 @@ typedef struct __go_channel chan; ...@@ -13,7 +15,7 @@ typedef struct __go_channel chan;
/* Do a channel receive with closed status. */ /* Do a channel receive with closed status. */
func chanrecv2(c *chan, val *byte) (received bool) { 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) { if (element_size > 8) {
return __go_receive_big(c, val, 0); return __go_receive_big(c, val, 0);
} else { } else {
......
...@@ -147,3 +147,6 @@ extern void __go_builtin_close (struct __go_channel *); ...@@ -147,3 +147,6 @@ extern void __go_builtin_close (struct __go_channel *);
extern int __go_chan_len (struct __go_channel *); extern int __go_chan_len (struct __go_channel *);
extern int __go_chan_cap (struct __go_channel *); extern int __go_chan_cap (struct __go_channel *);
extern uintptr_t __go_select (uintptr_t, _Bool, struct __go_channel **,
_Bool *);
...@@ -20,7 +20,10 @@ __go_receive_big (struct __go_channel *channel, void *val, _Bool for_select) ...@@ -20,7 +20,10 @@ __go_receive_big (struct __go_channel *channel, void *val, _Bool for_select)
size_t offset; size_t offset;
if (channel == NULL) if (channel == NULL)
__go_panic_msg ("receive from nil channel"); {
/* Block forever. */
__go_select (0, 0, NULL, NULL);
}
element_size = channel->element_type->__size; element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
......
...@@ -18,6 +18,13 @@ __go_receive_nonblocking_big (struct __go_channel* channel, void *val, ...@@ -18,6 +18,13 @@ __go_receive_nonblocking_big (struct __go_channel* channel, void *val,
size_t alloc_size; size_t alloc_size;
size_t offset; size_t offset;
if (channel == NULL)
{
if (closed != NULL)
*closed = 0;
return 0;
}
element_size = channel->element_type->__size; element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
......
...@@ -97,6 +97,14 @@ __go_receive_nonblocking_small (struct __go_channel *channel) ...@@ -97,6 +97,14 @@ __go_receive_nonblocking_small (struct __go_channel *channel)
uintptr_t element_size; uintptr_t element_size;
struct __go_receive_nonblocking_small ret; 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; element_size = channel->element_type->__size;
__go_assert (element_size <= sizeof (uint64_t)); __go_assert (element_size <= sizeof (uint64_t));
......
...@@ -270,7 +270,10 @@ __go_receive_small_closed (struct __go_channel *channel, _Bool for_select, ...@@ -270,7 +270,10 @@ __go_receive_small_closed (struct __go_channel *channel, _Bool for_select,
uint64_t ret; uint64_t ret;
if (channel == NULL) if (channel == NULL)
__go_panic_msg ("receive from nil channel"); {
/* Block forever. */
__go_select (0, 0, NULL, NULL);
}
element_size = channel->element_type->__size; element_size = channel->element_type->__size;
__go_assert (element_size <= sizeof (uint64_t)); __go_assert (element_size <= sizeof (uint64_t));
......
...@@ -45,18 +45,13 @@ chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i, ...@@ -45,18 +45,13 @@ chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i,
void *pv; void *pv;
__go_assert (ct->__common.__code == GO_CHAN); __go_assert (ct->__common.__code == GO_CHAN);
__go_assert (__go_type_descriptors_equal (ct->__element_type,
channel->element_type));
if (channel == NULL) if (__go_is_pointer_type (ct->__element_type))
__go_panic_msg ("send to nil channel");
if (__go_is_pointer_type (channel->element_type))
pv = &val_i; pv = &val_i;
else else
pv = (void *) val_i; pv = (void *) val_i;
element_size = channel->element_type->__size; element_size = ct->__element_type->__size;
if (element_size <= sizeof (uint64_t)) if (element_size <= sizeof (uint64_t))
{ {
union union
...@@ -112,12 +107,10 @@ chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb) ...@@ -112,12 +107,10 @@ chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb)
struct chanrecv_ret ret; struct chanrecv_ret ret;
__go_assert (ct->__common.__code == GO_CHAN); __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; pv = &ret.val;
else else
{ {
......
...@@ -17,7 +17,10 @@ __go_send_big (struct __go_channel* channel, const void *val, _Bool for_select) ...@@ -17,7 +17,10 @@ __go_send_big (struct __go_channel* channel, const void *val, _Bool for_select)
size_t offset; size_t offset;
if (channel == NULL) if (channel == NULL)
__go_panic_msg ("send to nil channel"); {
// Block forever.
__go_select (0, 0, NULL, NULL);
}
element_size = channel->element_type->__size; element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
......
...@@ -15,6 +15,9 @@ __go_send_nonblocking_big (struct __go_channel* channel, const void *val) ...@@ -15,6 +15,9 @@ __go_send_nonblocking_big (struct __go_channel* channel, const void *val)
size_t alloc_size; size_t alloc_size;
size_t offset; size_t offset;
if (channel == NULL)
return 0;
element_size = channel->element_type->__size; element_size = channel->element_type->__size;
alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t); alloc_size = (element_size + sizeof (uint64_t) - 1) / sizeof (uint64_t);
......
...@@ -93,6 +93,9 @@ __go_send_nonblocking_acquire (struct __go_channel *channel) ...@@ -93,6 +93,9 @@ __go_send_nonblocking_acquire (struct __go_channel *channel)
_Bool _Bool
__go_send_nonblocking_small (struct __go_channel *channel, uint64_t val) __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)); __go_assert (channel->element_type->__size <= sizeof (uint64_t));
if (!__go_send_nonblocking_acquire (channel)) if (!__go_send_nonblocking_acquire (channel))
......
...@@ -145,7 +145,10 @@ void ...@@ -145,7 +145,10 @@ void
__go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select) __go_send_small (struct __go_channel *channel, uint64_t val, _Bool for_select)
{ {
if (channel == NULL) 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)); __go_assert (channel->element_type->__size <= sizeof (uint64_t));
......
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