In libgo, system calls that return errors convert from an errno value to an error interface, a step that requires memory allocation. Memory allocation should be done while the goroutine is running on a thread that the Go scheduler knows about, which is to say not between calls to Entersyscall and Exitsyscall. This patch to libgo moves the interface conversion after the call to Exitsyscall. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline and 4.7 branch.
Ian
Index: libgo/go/syscall/mksyscall.awk =================================================================== --- libgo/go/syscall/mksyscall.awk (revision 186020) +++ libgo/go/syscall/mksyscall.awk (revision 186021) @@ -199,6 +199,7 @@ BEGIN { } printf("c_%s(%s)\n", cfnname, args) + seterr = 0 if (gofnresults != "") { fields = split(gofnresults, goresults, ", *") if (fields > 2) { @@ -218,13 +219,17 @@ BEGIN { gotype = goparam[2] if (goname == "err") { + print "\tvar errno Errno" + print "\tsetErrno := false" if (cfnresult ~ /^\*/) { print "\tif _r == nil {" } else { print "\tif _r < 0 {" } - print "\t\terr = GetErrno()" + print "\t\terrno = GetErrno()" + print "\t\tsetErrno = true" print "\t}" + seterr = 1 } else if (gotype == "uintptr" && cfnresult ~ /^\*/) { printf("\t%s = (%s)(unsafe.Pointer(_r))\n", goname, gotype) } else { @@ -243,6 +248,12 @@ BEGIN { print "\tExitsyscall()" } + if (seterr) { + print "\tif setErrno {" + print "\t\terr = errno" + print "\t}" + } + if (gofnresults != "") { print "\treturn" }