net: check read and write deadlines before doing syscalls

Otherwise a fast sender or receiver can make sockets always
readable or writable, preventing deadline checks from ever
occuring.

Update #4191 (fixes it with other CL, coming separately)
Fixes #4403

R=golang-dev, alex.brainman, dave, mikioh.mikioh
CC=golang-dev
https://golang.org/cl/6851096
diff --git a/src/pkg/net/timeout_test.go b/src/pkg/net/timeout_test.go
index 68d8ced..b5b2fa2 100644
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -6,11 +6,24 @@
 
 import (
 	"fmt"
+	"io"
+	"io/ioutil"
 	"runtime"
 	"testing"
 	"time"
 )
 
+func isTimeout(err error) bool {
+	e, ok := err.(Error)
+	return ok && e.Timeout()
+}
+
+type copyRes struct {
+	n   int64
+	err error
+	d   time.Duration
+}
+
 func testTimeout(t *testing.T, net, addr string, readFrom bool) {
 	c, err := Dial(net, addr)
 	if err != nil {
@@ -230,3 +243,191 @@
 	<-quit
 	<-lnquit
 }
+
+type neverEnding byte
+
+func (b neverEnding) Read(p []byte) (n int, err error) {
+	for i := range p {
+		p[i] = byte(b)
+	}
+	return len(p), nil
+}
+
+func TestVariousDeadlines1Proc(t *testing.T) {
+	testVariousDeadlines(t, 1)
+}
+
+func TestVariousDeadlines4Proc(t *testing.T) {
+	testVariousDeadlines(t, 4)
+}
+
+func testVariousDeadlines(t *testing.T, maxProcs int) {
+	defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(maxProcs))
+	ln := newLocalListener(t)
+	defer ln.Close()
+	donec := make(chan struct{})
+	defer close(donec)
+
+	testsDone := func() bool {
+		select {
+		case <-donec:
+			return true
+		}
+		return false
+	}
+
+	// The server, with no timeouts of its own, sending bytes to clients
+	// as fast as it can.
+	servec := make(chan copyRes)
+	go func() {
+		for {
+			c, err := ln.Accept()
+			if err != nil {
+				if !testsDone() {
+					t.Fatalf("Accept: %v", err)
+				}
+				return
+			}
+			go func() {
+				t0 := time.Now()
+				n, err := io.Copy(c, neverEnding('a'))
+				d := time.Since(t0)
+				c.Close()
+				servec <- copyRes{n, err, d}
+			}()
+		}
+	}()
+
+	for _, timeout := range []time.Duration{
+		1 * time.Nanosecond,
+		2 * time.Nanosecond,
+		5 * time.Nanosecond,
+		50 * time.Nanosecond,
+		100 * time.Nanosecond,
+		200 * time.Nanosecond,
+		500 * time.Nanosecond,
+		750 * time.Nanosecond,
+		1 * time.Microsecond,
+		5 * time.Microsecond,
+		25 * time.Microsecond,
+		250 * time.Microsecond,
+		500 * time.Microsecond,
+		1 * time.Millisecond,
+		5 * time.Millisecond,
+		100 * time.Millisecond,
+		250 * time.Millisecond,
+		500 * time.Millisecond,
+		1 * time.Second,
+	} {
+		numRuns := 3
+		if testing.Short() {
+			numRuns = 1
+			if timeout > 500*time.Microsecond {
+				continue
+			}
+		}
+		for run := 0; run < numRuns; run++ {
+			name := fmt.Sprintf("%v run %d/%d", timeout, run+1, numRuns)
+			t.Log(name)
+
+			c, err := Dial("tcp", ln.Addr().String())
+			if err != nil {
+				t.Fatalf("Dial: %v", err)
+			}
+			clientc := make(chan copyRes)
+			go func() {
+				t0 := time.Now()
+				c.SetDeadline(t0.Add(timeout))
+				n, err := io.Copy(ioutil.Discard, c)
+				d := time.Since(t0)
+				c.Close()
+				clientc <- copyRes{n, err, d}
+			}()
+
+			const tooLong = 2000 * time.Millisecond
+			select {
+			case res := <-clientc:
+				if isTimeout(res.err) {
+					t.Logf("for %v, good client timeout after %v, reading %d bytes", name, res.d, res.n)
+				} else {
+					t.Fatalf("for %v: client Copy = %d, %v (want timeout)", name, res.n, res.err)
+				}
+			case <-time.After(tooLong):
+				t.Fatalf("for %v: timeout (%v) waiting for client to timeout (%v) reading", name, tooLong, timeout)
+			}
+
+			select {
+			case res := <-servec:
+				t.Logf("for %v: server in %v wrote %d, %v", name, res.d, res.n, res.err)
+			case <-time.After(tooLong):
+				t.Fatalf("for %v, timeout waiting for server to finish writing", name)
+			}
+		}
+	}
+}
+
+// TestReadDeadlineDataAvailable tests that read deadlines work, even
+// if there's data ready to be read.
+func TestReadDeadlineDataAvailable(t *testing.T) {
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	servec := make(chan copyRes)
+	const msg = "data client shouldn't read, even though it it'll be waiting"
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		defer c.Close()
+		n, err := c.Write([]byte(msg))
+		servec <- copyRes{n: int64(n), err: err}
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	if res := <-servec; res.err != nil || res.n != int64(len(msg)) {
+		t.Fatalf("unexpected server Write: n=%d, err=%d; want n=%d, err=nil", res.n, res.err, len(msg))
+	}
+	c.SetReadDeadline(time.Now().Add(-5 * time.Second)) // in the psat.
+	buf := make([]byte, len(msg)/2)
+	n, err := c.Read(buf)
+	if n > 0 || !isTimeout(err) {
+		t.Fatalf("client read = %d (%q) err=%v; want 0, timeout", n, buf[:n], err)
+	}
+}
+
+// TestWriteDeadlineBufferAvailable tests that write deadlines work, even
+// if there's buffer space available to write.
+func TestWriteDeadlineBufferAvailable(t *testing.T) {
+	ln := newLocalListener(t)
+	defer ln.Close()
+
+	servec := make(chan copyRes)
+	go func() {
+		c, err := ln.Accept()
+		if err != nil {
+			t.Fatalf("Accept: %v", err)
+		}
+		defer c.Close()
+		c.SetWriteDeadline(time.Now().Add(-5 * time.Second)) // in the past
+		n, err := c.Write([]byte{'x'})
+		servec <- copyRes{n: int64(n), err: err}
+	}()
+
+	c, err := Dial("tcp", ln.Addr().String())
+	if err != nil {
+		t.Fatalf("Dial: %v", err)
+	}
+	defer c.Close()
+	res := <-servec
+	if res.n != 0 {
+		t.Errorf("Write = %d; want 0", res.n)
+	}
+	if !isTimeout(res.err) {
+		t.Errorf("Write error = %v; want timeout", res.err)
+	}
+}