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
This commit is contained in:
parent
5f0b897b2e
commit
bb96aa6726
@ -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.
|
||||
|
@ -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()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user