I've committed patch to libgo to update to the Go 1.2.1 release.  This
is a small patch that fixes a couple of serious bugs that have no source
code workarounds.  Bootstrapped and ran Go testsuite on
x86_64-unknown-linux-gnu.  Committed to mainline.

Ian

diff -r eb03648db396 libgo/MERGE
--- a/libgo/MERGE	Mon Mar 03 07:44:35 2014 -0800
+++ b/libgo/MERGE	Mon Mar 03 12:13:10 2014 -0800
@@ -1,4 +1,4 @@
-65bf677ab8d8
+0ddbdc3c7ce2
 
 The first line of this file holds the Mercurial revision number of the
 last merge done from the master library sources.
diff -r eb03648db396 libgo/go/database/sql/sql.go
--- a/libgo/go/database/sql/sql.go	Mon Mar 03 07:44:35 2014 -0800
+++ b/libgo/go/database/sql/sql.go	Mon Mar 03 12:13:10 2014 -0800
@@ -620,8 +620,8 @@
 	}
 
 	// If db.maxOpen > 0 and the number of open connections is over the limit
-	// or there are no free connection, then make a request and wait.
-	if db.maxOpen > 0 && (db.numOpen >= db.maxOpen || db.freeConn.Len() == 0) {
+	// and there are no free connection, make a request and wait.
+	if db.maxOpen > 0 && db.numOpen >= db.maxOpen && db.freeConn.Len() == 0 {
 		// Make the connRequest channel. It's buffered so that the
 		// connectionOpener doesn't block while waiting for the req to be read.
 		ch := make(chan interface{}, 1)
diff -r eb03648db396 libgo/go/database/sql/sql_test.go
--- a/libgo/go/database/sql/sql_test.go	Mon Mar 03 07:44:35 2014 -0800
+++ b/libgo/go/database/sql/sql_test.go	Mon Mar 03 12:13:10 2014 -0800
@@ -1005,6 +1005,29 @@
 	}
 }
 
+func TestSingleOpenConn(t *testing.T) {
+	db := newTestDB(t, "people")
+	defer closeDB(t, db)
+
+	db.SetMaxOpenConns(1)
+
+	rows, err := db.Query("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = rows.Close(); err != nil {
+		t.Fatal(err)
+	}
+	// shouldn't deadlock
+	rows, err = db.Query("SELECT|people|name|")
+	if err != nil {
+		t.Fatal(err)
+	}
+	if err = rows.Close(); err != nil {
+		t.Fatal(err)
+	}
+}
+
 // golang.org/issue/5323
 func TestStmtCloseDeps(t *testing.T) {
 	if testing.Short() {
diff -r eb03648db396 libgo/go/net/fd_windows.go
--- a/libgo/go/net/fd_windows.go	Mon Mar 03 07:44:35 2014 -0800
+++ b/libgo/go/net/fd_windows.go	Mon Mar 03 12:13:10 2014 -0800
@@ -513,12 +513,7 @@
 	})
 }
 
-func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
-	if err := fd.readLock(); err != nil {
-		return nil, err
-	}
-	defer fd.readUnlock()
-
+func (fd *netFD) acceptOne(toAddr func(syscall.Sockaddr) Addr, rawsa []syscall.RawSockaddrAny, o *operation) (*netFD, error) {
 	// Get new socket.
 	s, err := sysSocket(fd.family, fd.sotype, 0)
 	if err != nil {
@@ -537,9 +532,7 @@
 	}
 
 	// Submit accept request.
-	o := &fd.rop
 	o.handle = s
-	var rawsa [2]syscall.RawSockaddrAny
 	o.rsan = int32(unsafe.Sizeof(rawsa[0]))
 	_, err = rsrv.ExecIO(o, "AcceptEx", func(o *operation) error {
 		return syscall.AcceptEx(o.fd.sysfd, o.handle, (*byte)(unsafe.Pointer(&rawsa[0])), 0, uint32(o.rsan), uint32(o.rsan), &o.qty, &o.o)
@@ -556,6 +549,45 @@
 		return nil, &OpError{"Setsockopt", fd.net, fd.laddr, err}
 	}
 
+	return netfd, nil
+}
+
+func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
+	if err := fd.readLock(); err != nil {
+		return nil, err
+	}
+	defer fd.readUnlock()
+
+	o := &fd.rop
+	var netfd *netFD
+	var err error
+	var rawsa [2]syscall.RawSockaddrAny
+	for {
+		netfd, err = fd.acceptOne(toAddr, rawsa[:], o)
+		if err == nil {
+			break
+		}
+		// Sometimes we see WSAECONNRESET and ERROR_NETNAME_DELETED is
+		// returned here. These happen if connection reset is received
+		// before AcceptEx could complete. These errors relate to new
+		// connection, not to AcceptEx, so ignore broken connection and
+		// try AcceptEx again for more connections.
+		operr, ok := err.(*OpError)
+		if !ok {
+			return nil, err
+		}
+		errno, ok := operr.Err.(syscall.Errno)
+		if !ok {
+			return nil, err
+		}
+		switch errno {
+		case syscall.ERROR_NETNAME_DELETED, syscall.WSAECONNRESET:
+			// ignore these and try again
+		default:
+			return nil, err
+		}
+	}
+
 	// Get local and peer addr out of AcceptEx buffer.
 	var lrsa, rrsa *syscall.RawSockaddrAny
 	var llen, rlen int32
diff -r eb03648db396 libgo/runtime/mgc0.c
--- a/libgo/runtime/mgc0.c	Mon Mar 03 07:44:35 2014 -0800
+++ b/libgo/runtime/mgc0.c	Mon Mar 03 12:13:10 2014 -0800
@@ -1770,6 +1770,8 @@
 void
 runtime_gchelper(void)
 {
+	uint32 nproc;
+
 	gchelperstart();
 
 	// parallel mark for over gc roots
@@ -1786,7 +1788,8 @@
 
 	runtime_parfordo(work.sweepfor);
 	bufferList[runtime_m()->helpgc].busy = 0;
-	if(runtime_xadd(&work.ndone, +1) == work.nproc-1)
+	nproc = work.nproc;  // work.nproc can change right after we increment work.ndone
+	if(runtime_xadd(&work.ndone, +1) == nproc-1)
 		runtime_notewakeup(&work.alldone);
 }
 

Reply via email to