[Pkg-golang-commits] [golang] 01/03: Imported Upstream version 1.2.1

Michael Stapelberg michael at stapelberg.de
Sat Mar 8 17:02:04 UTC 2014


This is an automated email from the git hooks/post-receive script.

stapelberg pushed a commit to branch debian-sid
in repository golang.

commit c8bf49ef8a92e2337b69c14b9b88396efe498600
Author: Michael Stapelberg <stapelberg at debian.org>
Date:   Mon Mar 3 17:40:19 2014 +0100

    Imported Upstream version 1.2.1
---
 VERSION                           |   2 +-
 doc/devel/release.html            |   6 ++
 doc/install.html                  |   2 +-
 src/pkg/database/sql/sql.go       |   4 +-
 src/pkg/database/sql/sql_test.go  |  23 ++++++
 src/pkg/net/fd_windows.go         |  48 ++++++++++---
 src/pkg/net/net_windows_test.go   | 146 ++++++++++++++++++++++++++++++++++++++
 src/pkg/runtime/mgc0.c            |   5 +-
 src/pkg/runtime/mprof.goc         |   4 +-
 src/pkg/runtime/proc.c            |   4 +-
 src/pkg/runtime/sys_x86.c         |  13 ++++
 src/pkg/runtime/traceback_arm.c   |  12 ++++
 src/pkg/runtime/traceback_x86.c   |  10 +++
 src/pkg/syscall/ztypes_windows.go |   2 +
 14 files changed, 264 insertions(+), 17 deletions(-)

diff --git a/VERSION b/VERSION
index 7e7b355..39dbf64 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-go1.2
\ No newline at end of file
+go1.2.1
\ No newline at end of file
diff --git a/doc/devel/release.html b/doc/devel/release.html
index d31f793..5511db7 100644
--- a/doc/devel/release.html
+++ b/doc/devel/release.html
@@ -363,6 +363,12 @@ variable to build and install your own code and external libraries outside of
 the Go tree (and avoid writing Makefiles).
 </p>
 
+<h3 id="go1.2.minor">Minor revisions</h3>
+
+<p>
+go1.2.1 (released 2014/03/02) includes bug fixes to the <code>runtime</code>, <code>net</code>, and <code>database/sql</code> packages.
+See the <a href="https://code.google.com/p/go/source/list?name=release-branch.go1.2&r=7ada9e760ce34e78aee5b476c9621556d0fa5d31">change history</a> for details.
+</p>
 
 <h3 id="r58.minor">Minor revisions</h3>
 
diff --git a/doc/install.html b/doc/install.html
index f08c766..af4c8f3 100644
--- a/doc/install.html
+++ b/doc/install.html
@@ -76,7 +76,7 @@ and extract it into <code>/usr/local</code>, creating a Go tree in
 </p>
 
 <pre>
-tar -C /usr/local -xzf go1.1.linux-amd64.tar.gz
+tar -C /usr/local -xzf go1.2.1.linux-amd64.tar.gz
 </pre>
 
 <p>
diff --git a/src/pkg/database/sql/sql.go b/src/pkg/database/sql/sql.go
index dddf5a3..84a0965 100644
--- a/src/pkg/database/sql/sql.go
+++ b/src/pkg/database/sql/sql.go
@@ -620,8 +620,8 @@ func (db *DB) conn() (*driverConn, error) {
 	}
 
 	// 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 --git a/src/pkg/database/sql/sql_test.go b/src/pkg/database/sql/sql_test.go
index 093c0d6..787a5c9 100644
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/pkg/database/sql/sql_test.go
@@ -1005,6 +1005,29 @@ func TestMaxOpenConns(t *testing.T) {
 	}
 }
 
+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 --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 64d56c7..630fc5e 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -513,12 +513,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (int, error) {
 	})
 }
 
-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 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
 	}
 
 	// 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 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (*netFD, error) {
 		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 --git a/src/pkg/net/net_windows_test.go b/src/pkg/net/net_windows_test.go
new file mode 100644
index 0000000..8b1c9cd
--- /dev/null
+++ b/src/pkg/net/net_windows_test.go
@@ -0,0 +1,146 @@
+// Copyright 2014 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package net
+
+import (
+	"bufio"
+	"fmt"
+	"io"
+	"os"
+	"os/exec"
+	"syscall"
+	"testing"
+	"time"
+)
+
+func TestAcceptIgnoreSomeErrors(t *testing.T) {
+	recv := func(ln Listener) (string, error) {
+		c, err := ln.Accept()
+		if err != nil {
+			// Display windows errno in error message.
+			operr, ok := err.(*OpError)
+			if !ok {
+				return "", err
+			}
+			errno, ok := operr.Err.(syscall.Errno)
+			if !ok {
+				return "", err
+			}
+			return "", fmt.Errorf("%v (windows errno=%d)", err, errno)
+		}
+		defer c.Close()
+
+		b := make([]byte, 100)
+		n, err := c.Read(b)
+		if err != nil && err != io.EOF {
+			return "", err
+		}
+		return string(b[:n]), nil
+	}
+
+	send := func(addr string, data string) error {
+		c, err := Dial("tcp", addr)
+		if err != nil {
+			return err
+		}
+		defer c.Close()
+
+		b := []byte(data)
+		n, err := c.Write(b)
+		if err != nil {
+			return err
+		}
+		if n != len(b) {
+			return fmt.Errorf(`Only %d chars of string "%s" sent`, n, data)
+		}
+		return nil
+	}
+
+	if envaddr := os.Getenv("GOTEST_DIAL_ADDR"); envaddr != "" {
+		// In child process.
+		c, err := Dial("tcp", envaddr)
+		if err != nil {
+			t.Fatalf("Dial failed: %v", err)
+		}
+		fmt.Printf("sleeping\n")
+		time.Sleep(time.Minute) // process will be killed here
+		c.Close()
+	}
+
+	ln, err := Listen("tcp", "127.0.0.1:0")
+	if err != nil {
+		t.Fatalf("Listen failed: %v", err)
+	}
+	defer ln.Close()
+
+	// Start child process that connects to our listener.
+	cmd := exec.Command(os.Args[0], "-test.run=TestAcceptIgnoreSomeErrors")
+	cmd.Env = append(os.Environ(), "GOTEST_DIAL_ADDR="+ln.Addr().String())
+	stdout, err := cmd.StdoutPipe()
+	if err != nil {
+		t.Fatalf("cmd.StdoutPipe failed: %v", err)
+	}
+	err = cmd.Start()
+	if err != nil {
+		t.Fatalf("cmd.Start failed: %v\n%s\n", err)
+	}
+	outReader := bufio.NewReader(stdout)
+	for {
+		s, err := outReader.ReadString('\n')
+		if err != nil {
+			t.Fatalf("reading stdout failed: %v", err)
+		}
+		if s == "sleeping\n" {
+			break
+		}
+	}
+	defer cmd.Wait() // ignore error - we know it is getting killed
+
+	const alittle = 100 * time.Millisecond
+	time.Sleep(alittle)
+	cmd.Process.Kill() // the only way to trigger the errors
+	time.Sleep(alittle)
+
+	// Send second connection data (with delay in a separate goroutine).
+	result := make(chan error)
+	go func() {
+		time.Sleep(alittle)
+		err = send(ln.Addr().String(), "abc")
+		if err != nil {
+			result <- err
+		}
+		result <- nil
+	}()
+	defer func() {
+		err := <-result
+		if err != nil {
+			t.Fatalf("send failed: %v", err)
+		}
+	}()
+
+	// Receive first or second connection.
+	s, err := recv(ln)
+	if err != nil {
+		t.Fatalf("recv failed: %v", err)
+	}
+	switch s {
+	case "":
+		// First connection data is received, lets get second connection data.
+	case "abc":
+		// First connection is lost forever, but that is ok.
+		return
+	default:
+		t.Fatalf(`"%s" received from recv, but "" or "abc" expected`, s)
+	}
+
+	// Get second connection data.
+	s, err = recv(ln)
+	if err != nil {
+		t.Fatalf("recv failed: %v", err)
+	}
+	if s != "abc" {
+		t.Fatalf(`"%s" received from recv, but "abc" expected`, s)
+	}
+}
diff --git a/src/pkg/runtime/mgc0.c b/src/pkg/runtime/mgc0.c
index 4b2108b..761f128 100644
--- a/src/pkg/runtime/mgc0.c
+++ b/src/pkg/runtime/mgc0.c
@@ -1798,6 +1798,8 @@ runtime·memorydump(void)
 void
 runtime·gchelper(void)
 {
+	int32 nproc;
+
 	gchelperstart();
 
 	// parallel mark for over gc roots
@@ -1814,7 +1816,8 @@ runtime·gchelper(void)
 
 	runtime·parfordo(work.sweepfor);
 	bufferList[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);
 }
 
diff --git a/src/pkg/runtime/mprof.goc b/src/pkg/runtime/mprof.goc
index 5b92cec..4ae74f0 100644
--- a/src/pkg/runtime/mprof.goc
+++ b/src/pkg/runtime/mprof.goc
@@ -477,7 +477,7 @@ saveg(uintptr pc, uintptr sp, G *gp, TRecord *r)
 {
 	int32 n;
 	
-	n = runtime·gentraceback((uintptr)pc, (uintptr)sp, 0, gp, 0, r->stk, nelem(r->stk), nil, nil, false);
+	n = runtime·gentraceback(pc, sp, 0, gp, 0, r->stk, nelem(r->stk), nil, nil, false);
 	if(n < nelem(r->stk))
 		r->stk[n] = 0;
 }
@@ -505,7 +505,7 @@ func GoroutineProfile(b Slice) (n int, ok bool) {
 			for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
 				if(gp == g || gp->status == Gdead)
 					continue;
-				saveg(gp->sched.pc, gp->sched.sp, gp, r++);
+				saveg(~(uintptr)0, ~(uintptr)0, gp, r++);
 			}
 		}
 	
diff --git a/src/pkg/runtime/proc.c b/src/pkg/runtime/proc.c
index de26c72..ed3e1e7 100644
--- a/src/pkg/runtime/proc.c
+++ b/src/pkg/runtime/proc.c
@@ -276,7 +276,7 @@ runtime·tracebackothers(G *me)
 	if((gp = m->curg) != nil && gp != me) {
 		runtime·printf("\n");
 		runtime·goroutineheader(gp);
-		runtime·traceback(gp->sched.pc, gp->sched.sp, gp->sched.lr, gp);
+		runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, gp);
 	}
 
 	for(gp = runtime·allg; gp != nil; gp = gp->alllink) {
@@ -290,7 +290,7 @@ runtime·tracebackothers(G *me)
 			runtime·printf("\tgoroutine running on other thread; stack unavailable\n");
 			runtime·printcreatedby(gp);
 		} else
-			runtime·traceback(gp->sched.pc, gp->sched.sp, gp->sched.lr, gp);
+			runtime·traceback(~(uintptr)0, ~(uintptr)0, 0, gp);
 	}
 }
 
diff --git a/src/pkg/runtime/sys_x86.c b/src/pkg/runtime/sys_x86.c
index e68ff51..0df6dfb 100644
--- a/src/pkg/runtime/sys_x86.c
+++ b/src/pkg/runtime/sys_x86.c
@@ -37,6 +37,19 @@ runtime·rewindmorestack(Gobuf *gobuf)
 		gobuf->pc = gobuf->pc + 2 + *(int8*)(pc+1);
 		return;
 	}
+ 	if(pc[0] == 0xcc) {
+ 		// This is a breakpoint inserted by gdb.  We could use
+ 		// runtime·findfunc to find the function.  But if we
+ 		// do that, then we will continue execution at the
+ 		// function entry point, and we will not hit the gdb
+ 		// breakpoint.  So for this case we don't change
+ 		// gobuf->pc, so that when we return we will execute
+ 		// the jump instruction and carry on.  This means that
+ 		// stack unwinding may not work entirely correctly
+ 		// (http://golang.org/issue/5723) but the user is
+ 		// running under gdb anyhow.
+ 		return;
+	}
 	runtime·printf("runtime: pc=%p %x %x %x %x %x\n", pc, pc[0], pc[1], pc[2], pc[3], pc[4]);
 	runtime·throw("runtime: misuse of rewindmorestack");
 }
diff --git a/src/pkg/runtime/traceback_arm.c b/src/pkg/runtime/traceback_arm.c
index 341aa20..8a3685e 100644
--- a/src/pkg/runtime/traceback_arm.c
+++ b/src/pkg/runtime/traceback_arm.c
@@ -20,6 +20,18 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
 	Stktop *stk;
 	String file;
 
+	if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp.
+		if(gp->syscallstack != (uintptr)nil) {
+			pc0 = gp->syscallpc;
+			sp0 = gp->syscallsp;
+			lr0 = 0;
+		} else {
+			pc0 = gp->sched.pc;
+			sp0 = gp->sched.sp;
+			lr0 = gp->sched.lr;
+		}
+	}
+
 	nprint = 0;
 	runtime·memclr((byte*)&frame, sizeof frame);
 	frame.pc = pc0;
diff --git a/src/pkg/runtime/traceback_x86.c b/src/pkg/runtime/traceback_x86.c
index d658e8f..8e3063f 100644
--- a/src/pkg/runtime/traceback_x86.c
+++ b/src/pkg/runtime/traceback_x86.c
@@ -30,6 +30,16 @@ runtime·gentraceback(uintptr pc0, uintptr sp0, uintptr lr0, G *gp, int32 skip,
 	String file;
 
 	USED(lr0);
+	
+	if(pc0 == ~(uintptr)0 && sp0 == ~(uintptr)0) { // Signal to fetch saved values from gp.
+		if(gp->syscallstack != (uintptr)nil) {
+			pc0 = gp->syscallpc;
+			sp0 = gp->syscallsp;
+		} else {
+			pc0 = gp->sched.pc;
+			sp0 = gp->sched.sp;
+		}
+	}
 
 	nprint = 0;
 	runtime·memclr((byte*)&frame, sizeof frame);
diff --git a/src/pkg/syscall/ztypes_windows.go b/src/pkg/syscall/ztypes_windows.go
index bdc15ce..a5681d7 100644
--- a/src/pkg/syscall/ztypes_windows.go
+++ b/src/pkg/syscall/ztypes_windows.go
@@ -11,6 +11,7 @@ const (
 	ERROR_ACCESS_DENIED       Errno = 5
 	ERROR_NO_MORE_FILES       Errno = 18
 	ERROR_HANDLE_EOF          Errno = 38
+	ERROR_NETNAME_DELETED     Errno = 64
 	ERROR_FILE_EXISTS         Errno = 80
 	ERROR_BROKEN_PIPE         Errno = 109
 	ERROR_BUFFER_OVERFLOW     Errno = 111
@@ -23,6 +24,7 @@ const (
 	ERROR_IO_PENDING          Errno = 997
 	ERROR_NOT_FOUND           Errno = 1168
 	WSAEACCES                 Errno = 10013
+	WSAECONNRESET             Errno = 10054
 )
 
 const (

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-golang/golang.git



More information about the pkg-golang-commits mailing list