go/loader: fix fd leak and limit calls to ioutil.ReadDir

This makes 'ulimit -n 128; go test -short -v' pass.
It did not before, and that was breaking the openbsd/386 builder.

For golang/go#11811.

Change-Id: Idfdb2f4007ed06c6084486c0e58a561add552d2c
Reviewed-on: https://go-review.googlesource.com/13695
Reviewed-by: Robert Griesemer <gri@golang.org>
diff --git a/go/loader/cgo.go b/go/loader/cgo.go
index 299e725..fb39e53 100644
--- a/go/loader/cgo.go
+++ b/go/loader/cgo.go
@@ -87,9 +87,9 @@
 		if err != nil {
 			return nil, err
 		}
-		defer rd.Close()
 		display := filepath.Join(bp.Dir, cgoDisplayFiles[i])
 		f, err := parser.ParseFile(fset, display, rd, mode)
+		rd.Close()
 		if err != nil {
 			return nil, err
 		}
diff --git a/go/loader/loader.go b/go/loader/loader.go
index bbacc5b..1d3ead0 100644
--- a/go/loader/loader.go
+++ b/go/loader/loader.go
@@ -449,7 +449,9 @@
 		conf.FindPackage = func(ctxt *build.Context, path string) (*build.Package, error) {
 			// TODO(adonovan): cache calls to build.Import
 			// so we don't do it three times per test package.
+			ioLimit <- true
 			bp, err := ctxt.Import(path, conf.Cwd, 0)
+			<-ioLimit
 			if _, ok := err.(*build.NoGoError); ok {
 				return bp, nil // empty directory is not an error
 			}
diff --git a/go/loader/util.go b/go/loader/util.go
index 0404e99..3b64856 100644
--- a/go/loader/util.go
+++ b/go/loader/util.go
@@ -19,7 +19,7 @@
 
 // We use a counting semaphore to limit
 // the number of parallel I/O calls per process.
-var sema = make(chan bool, 10)
+var ioLimit = make(chan bool, 10)
 
 // parseFiles parses the Go source files within directory dir and
 // returns the ASTs of the ones that could be at least partially parsed,
@@ -42,10 +42,10 @@
 		}
 		wg.Add(1)
 		go func(i int, file string) {
-			sema <- true // wait
+			ioLimit <- true // wait
 			defer func() {
 				wg.Done()
-				<-sema // signal
+				<-ioLimit // signal
 			}()
 			var rd io.ReadCloser
 			var err error