OSDN Git Service

Block forever on send/receive to/from nil channel.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Sep 2011 22:56:32 +0000 (22:56 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 16 Sep 2011 22:56:32 +0000 (22:56 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@178920 138bc75d-0d04-0410-961f-82ee72b054a4

12 files changed:
gcc/testsuite/go.test/test/chan/select3.go
libgo/runtime/chan.goc
libgo/runtime/channel.h
libgo/runtime/go-rec-big.c
libgo/runtime/go-rec-nb-big.c
libgo/runtime/go-rec-nb-small.c
libgo/runtime/go-rec-small.c
libgo/runtime/go-reflect-chan.c
libgo/runtime/go-send-big.c
libgo/runtime/go-send-nb-big.c
libgo/runtime/go-send-nb-small.c
libgo/runtime/go-send-small.c

index b4e8f8e..d919de3 100644 (file)
@@ -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:
index acfff85..c3cc3e3 100644 (file)
@@ -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 {
index d4f1632..9176c68 100644 (file)
@@ -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 *);
index 580ccb0..d45e90a 100644 (file)
@@ -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);
index 8c315b1..659ea1d 100644 (file)
@@ -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);
 
index eb0a25e..0543920 100644 (file)
@@ -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));
 
index 946a18c..d947632 100644 (file)
@@ -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));
index e8b4366..6f6693b 100644 (file)
@@ -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
     {
index 0b4aa04..61d4a0f 100644 (file)
@@ -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);
index 1274859..e039874 100644 (file)
@@ -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);
 
index 0a25ba3..51914db 100644 (file)
@@ -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))
index 8e21d36..25e3c82 100644 (file)
@@ -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));