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"
     }

Reply via email to