]> Cypherpunks repositories - gostls13.git/commitdiff
gc: select receive bug fix
authorRuss Cox <rsc@golang.org>
Wed, 2 Feb 2011 23:34:09 +0000 (18:34 -0500)
committerRuss Cox <rsc@golang.org>
Wed, 2 Feb 2011 23:34:09 +0000 (18:34 -0500)
Affects receive using := when new variable escapes to heap.

Fixes #1468.

R=ken2
CC=golang-dev
https://golang.org/cl/4119052

src/cmd/gc/select.c
test/fixedbugs/bug320.go [new file with mode: 0644]

index 5686e959952c93532123ce7d218a49504f6804b4..58a147745d7a4a4dd360ed0254c674b340aa8bd6 100644 (file)
@@ -157,7 +157,7 @@ walkselect(Node *sel)
                        if(n->left == N || isblank(n->left))
                                n->left = nodnil();
                        else if(n->left->op == ONAME &&
-                                       (!n->colas || (n->class&PHEAP) == 0) &&
+                                       (!n->colas || (n->left->class&PHEAP) == 0) &&
                                        convertop(ch->type->type, n->left->type, nil) == OCONVNOP) {
                                n->left = nod(OADDR, n->left, N);
                                n->left->etype = 1;  // pointer does not escape
@@ -170,9 +170,9 @@ walkselect(Node *sel)
                                typecheck(&a, Erv);
                                r = nod(OAS, n->left, tmp);
                                typecheck(&r, Etop);
+                               cas->nbody = concat(list1(r), cas->nbody);
                                cas->nbody = concat(n->ninit, cas->nbody);
                                n->ninit = nil;
-                               cas->nbody = concat(list1(r), cas->nbody);
                                n->left = a;
                        }
                }
diff --git a/test/fixedbugs/bug320.go b/test/fixedbugs/bug320.go
new file mode 100644 (file)
index 0000000..06d41f2
--- /dev/null
@@ -0,0 +1,45 @@
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2011 The Go Authors.  All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+func main() {
+       c := make(chan int, 1)
+       dummy := make(chan int)
+       v := 0x12345678
+       for i := 0; i < 10; i++ {
+               // 6g had a bug that caused select to pass &t to
+               // selectrecv before allocating the memory for t,
+               // which caused non-deterministic crashes.
+               // This test looks for the bug by checking that the
+               // value received actually ends up in t.
+               // If the allocation happens after storing through
+               // whatever garbage &t holds, the later reference
+               // to t in the case body will use the new pointer and
+               // not see the received value.
+               v += 0x1020304
+               c <- v
+               select {
+               case t := <-c:
+                       go func() {
+                               f(t)
+                       }()
+                       escape(&t)
+                       if t != v {
+                               println(i, v, t)
+                               panic("wrong values")
+                       }
+               case dummy <- 1:
+               }
+       }
+}
+
+func escape(*int) {
+}
+
+func f(int) {
+}
+