Skip to content

Commit bb0fae6

Browse files
billziss-ghianlancetaylor
authored andcommitted
runtime: handle windows callback on non-go thread
Adds an extra M in mstartm0 and accounts for it in checkdead. This allows Windows callbacks created with syscall.NewCallback and syscall.NewCallbackCDecl to be called on a non-Go thread. Fixes #6751 Change-Id: I57626bc009a6370b9ca0827ab64b14b01dec39d4 GitHub-Last-Rev: d429e3e GitHub-Pull-Request: #25575 Reviewed-on: https://go-review.googlesource.com/114802 Reviewed-by: Alex Brainman <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Run-TryBot: Ian Lance Taylor <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 4a2bec9 commit bb0fae6

File tree

2 files changed

+18
-5
lines changed

2 files changed

+18
-5
lines changed

src/runtime/proc.go

+18-3
Original file line numberDiff line numberDiff line change
@@ -1293,7 +1293,9 @@ func mstart1() {
12931293
//go:yeswritebarrierrec
12941294
func mstartm0() {
12951295
// Create an extra M for callbacks on threads not created by Go.
1296-
if iscgo && !cgoHasExtraM {
1296+
// An extra M is also needed on Windows for callbacks created by
1297+
// syscall.NewCallback. See issue #6751 for details.
1298+
if (iscgo || GOOS == "windows") && !cgoHasExtraM {
12971299
cgoHasExtraM = true
12981300
newextram()
12991301
}
@@ -1618,8 +1620,12 @@ func allocm(_p_ *p, fn func()) *m {
16181620
// put the m back on the list.
16191621
//go:nosplit
16201622
func needm(x byte) {
1621-
if iscgo && !cgoHasExtraM {
1623+
if (iscgo || GOOS == "windows") && !cgoHasExtraM {
16221624
// Can happen if C/C++ code calls Go from a global ctor.
1625+
// Can also happen on Windows if a global ctor uses a
1626+
// callback created by syscall.NewCallback. See issue #6751
1627+
// for details.
1628+
//
16231629
// Can not throw, because scheduler is not initialized yet.
16241630
write(2, unsafe.Pointer(&earlycgocallback[0]), int32(len(earlycgocallback)))
16251631
exit(1)
@@ -4215,8 +4221,17 @@ func checkdead() {
42154221
return
42164222
}
42174223

4224+
// If we are not running under cgo, but we have an extra M then account
4225+
// for it. (It is possible to have an extra M on Windows without cgo to
4226+
// accommodate callbacks created by syscall.NewCallback. See issue #6751
4227+
// for details.)
4228+
var run0 int32
4229+
if !iscgo && cgoHasExtraM {
4230+
run0 = 1
4231+
}
4232+
42184233
run := mcount() - sched.nmidle - sched.nmidlelocked - sched.nmsys
4219-
if run > 0 {
4234+
if run > run0 {
42204235
return
42214236
}
42224237
if run < 0 {

src/runtime/syscall_windows_test.go

-2
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,6 @@ func TestBlockingCallback(t *testing.T) {
251251
}
252252

253253
func TestCallbackInAnotherThread(t *testing.T) {
254-
t.Skip("Skipping failing test (see golang.org/issue/6751 for details)")
255-
256254
d := GetDLL(t, "kernel32.dll")
257255

258256
f := func(p uintptr) uintptr {

0 commit comments

Comments
 (0)