runtime: don't crash if no p in kickoff
authorIan Lance Taylor <ian@gcc.gnu.org>
Fri, 23 Jun 2017 16:05:44 +0000 (16:05 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Fri, 23 Jun 2017 16:05:44 +0000 (16:05 +0000)
    The kickoff function for g0 can be invoked without a p, for example
    from mcall(exitsyscall0) in exitsyscall after exitsyscall has cleared
    the p field. The assignment gp.param = nil will invoke a write barrier.
    If gp.param is not already nil, this will require a p. Avoid the problem
    for a specific case that is known to be OK: when the value in gp.param
    is a *g.

    Reviewed-on: https://go-review.googlesource.com/46512

From-SVN: r249595

gcc/go/gofrontend/MERGE
libgo/go/runtime/proc.go

index 02be610b167085c0a154e6058286857c243aa462..473eeca22daaa9e4b848f221f4f9311be66f6dfc 100644 (file)
@@ -1,4 +1,4 @@
-29c61dc3c5151df5de9362b7882ccf04679df976
+f107cc8bced1939b0083231fc1ea24669ca4832c
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 77b624ba61216c31c764258bc4a3aacd44e0126f..6b6f9c9c379c3ce30f77153cb00bbf5a263e8852 100644 (file)
@@ -1097,7 +1097,25 @@ func kickoff() {
        fv := gp.entry
        param := gp.param
        gp.entry = nil
+
+       // When running on the g0 stack we can wind up here without a p,
+       // for example from mcall(exitsyscall0) in exitsyscall.
+       // Setting gp.param = nil will call a write barrier, and if
+       // there is no p that write barrier will crash. When called from
+       // mcall the gp.param value will be a *g, which we don't need to
+       // shade since we know it will be kept alive elsewhere. In that
+       // case clear the field using uintptr so that the write barrier
+       // does nothing.
+       if gp.m.p == 0 {
+               if gp == gp.m.g0 && gp.param == unsafe.Pointer(gp.m.curg) {
+                       *(*uintptr)(unsafe.Pointer(&gp.param)) = 0
+               } else {
+                       throw("no p in kickoff")
+               }
+       }
+
        gp.param = nil
+
        fv(param)
        goexit1()
 }