Block forever on send/receive to/from nil channel.
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 16 Sep 2011 22:56:32 +0000 (22:56 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 16 Sep 2011 22:56:32 +0000 (22:56 +0000)
From-SVN: r178920

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 b4e8f8e4bf9589e5ef7da9b79bbbad9e9a488f9e..d919de3e0d957eefbb15ca0850fed94cd1d3e6a7 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 acfff859ee00e283f8266ffa7fadd18ee851b04a..c3cc3e39879121209576e7742d7701200b077084 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 d4f1632a449f020c0fd358e019dd6c58f6e6e784..9176c68f692f2f5cede8a17d8aa8e4cc2ddc4401 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 580ccb0671923781a86960e61164036fc4262cc6..d45e90af476d2281e66120db3ed4cb4021909906 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 8c315b19af73777767b497c5bd21121f1b8be174..659ea1dc33db5da24d650ad812ccc4e1fb136c05 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 eb0a25e12b7d63b4fc9bc1651afa7002857f5ee9..054392009c311a5612a849033a2ead6e534a7c69 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 946a18c0c8e726271f8241594b3b5f49a3301a64..d94763296941b631aa9e214f64cbc7575f7d283e 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 e8b4366dc57326cf266c48d606bf8f6b8437cddd..6f6693b6b54a61d3abba059a70a7cd3359e18d50 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 0b4aa046d127dae8624f0f453351bf1d94e7dfce..61d4a0f13d9247afa2c1abbf8e65dc12c80bcc20 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 127485917062689d2d3ff1f2295bf36c2d6de0a5..e039874ef9abe704b18b5b2c4d24bef6867dcde4 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 0a25ba369ea548bab2e3bad304682a9d991db513..51914dbfa3c4591fb039af6f6e6f3de730025201 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 8e21d368588f32d4a6f3655024da4899ee93ffe0..25e3c82bd89e41b92d415980a89f41287b91b2b5 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));