Commit bb96aa67 by Ian Lance Taylor

runtime: don't crash if no p in kickoff

    
    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
parent 5f0b897b
29c61dc3c5151df5de9362b7882ccf04679df976 f107cc8bced1939b0083231fc1ea24669ca4832c
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -1097,7 +1097,25 @@ func kickoff() { ...@@ -1097,7 +1097,25 @@ func kickoff() {
fv := gp.entry fv := gp.entry
param := gp.param param := gp.param
gp.entry = nil 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 gp.param = nil
fv(param) fv(param)
goexit1() goexit1()
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment