mirror of git://gcc.gnu.org/git/gcc.git
Block forever on send/receive to/from nil channel.
From-SVN: r178920
This commit is contained in:
parent
e7f799cecc
commit
31aeabd3c5
|
@ -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
|
||||||
#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;
|
||||||
/* 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 *);
|
||||||
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)
|
||||||
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,
|
||||||
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)
|
||||||
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,
|
||||||
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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
_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
|
||||||
__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));
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue