diff --git a/doc/go1.html b/doc/go1.html
index 2018b1aca2d..4b985071ef6 100644
--- a/doc/go1.html
+++ b/doc/go1.html
@@ -750,6 +750,17 @@ Gofix will update the few programs that are affected except for
uses of RawURL
, which must be fixed by hand.
In Go 1, the various SetTimeout
,
+SetReadTimeout
, and SetWriteTimeout
methods
+have been replaced with SetDeadline
,
+SetReadDeadline
, and SetWriteDeadline
,
+respectively. Rather than taking a timeout value in nanoseconds that
+apply to any activity on the connection, the new methods set an
+absolute deadline (as a time.Time
value) after which
+reads and writes will time out and no longer block.
@@ -957,8 +968,8 @@ documentation for a package is created with:
-where the new mode parameter specifies the operation mode:
-if set to
AllDecls
, all declarations
+where the new mode
parameter specifies the operation mode:
+if set to AllDecls
, all declarations
(not just exported ones) are considered.
The function NewFileDoc
was removed, and the function
CommentText
has become the method
diff --git a/doc/go1.tmpl b/doc/go1.tmpl
index d8419f8459e..8d295d6e454 100644
--- a/doc/go1.tmpl
+++ b/doc/go1.tmpl
@@ -654,6 +654,17 @@ Gofix will update the few programs that are affected except for
uses of RawURL
, which must be fixed by hand.
In Go 1, the various SetTimeout
,
+SetReadTimeout
, and SetWriteTimeout
methods
+have been replaced with SetDeadline
,
+SetReadDeadline
, and SetWriteDeadline
,
+respectively. Rather than taking a timeout value in nanoseconds that
+apply to any activity on the connection, the new methods set an
+absolute deadline (as a time.Time
value) after which
+reads and writes will time out and no longer block.
@@ -861,8 +872,8 @@ documentation for a package is created with:
-where the new mode parameter specifies the operation mode:
-if set to
AllDecls
, all declarations
+where the new mode
parameter specifies the operation mode:
+if set to AllDecls
, all declarations
(not just exported ones) are considered.
The function NewFileDoc
was removed, and the function
CommentText
has become the method
diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go
index 6a03fa8042a..e6cee1278c3 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/pkg/crypto/tls/conn.go
@@ -15,6 +15,7 @@ import (
"io"
"net"
"sync"
+ "time"
)
// A Conn represents a secured connection.
@@ -86,24 +87,23 @@ func (c *Conn) RemoteAddr() net.Addr {
return c.conn.RemoteAddr()
}
-// SetTimeout sets the read deadline associated with the connection.
+// SetDeadline sets the read deadline associated with the connection.
// There is no write deadline.
-func (c *Conn) SetTimeout(nsec int64) error {
- return c.conn.SetTimeout(nsec)
+// A zero value for t means Read will not time out.
+func (c *Conn) SetDeadline(t time.Time) error {
+ return c.conn.SetDeadline(t)
}
-// SetReadTimeout sets the time (in nanoseconds) that
-// Read will wait for data before returning a net.Error
-// with Timeout() == true.
-// Setting nsec == 0 (the default) disables the deadline.
-func (c *Conn) SetReadTimeout(nsec int64) error {
- return c.conn.SetReadTimeout(nsec)
+// SetReadDeadline sets the read deadline on the underlying connection.
+// A zero value for t means Read will not time out.
+func (c *Conn) SetReadDeadline(t time.Time) error {
+ return c.conn.SetReadDeadline(t)
}
-// SetWriteTimeout exists to satisfy the net.Conn interface
+// SetWriteDeadline exists to satisfy the net.Conn interface
// but is not implemented by TLS. It always returns an error.
-func (c *Conn) SetWriteTimeout(nsec int64) error {
- return errors.New("TLS does not support SetWriteTimeout")
+func (c *Conn) SetWriteDeadline(t time.Time) error {
+ return errors.New("TLS does not support SetWriteDeadline")
}
// A halfConn represents one direction of the record layer
@@ -744,7 +744,7 @@ func (c *Conn) Write(b []byte) (n int, err error) {
}
// Read can be made to time out and return a net.Error with Timeout() == true
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *Conn) Read(b []byte) (n int, err error) {
if err = c.Handshake(); err != nil {
return
diff --git a/src/pkg/exp/ssh/tcpip.go b/src/pkg/exp/ssh/tcpip.go
index bee41eeb0db..e0c47bca1fc 100644
--- a/src/pkg/exp/ssh/tcpip.go
+++ b/src/pkg/exp/ssh/tcpip.go
@@ -9,6 +9,7 @@ import (
"fmt"
"io"
"net"
+ "time"
)
// Dial initiates a connection to the addr from the remote host.
@@ -107,27 +108,25 @@ func (t *tcpchanconn) RemoteAddr() net.Addr {
return t.raddr
}
-// SetTimeout sets the read and write deadlines associated
+// SetDeadline sets the read and write deadlines associated
// with the connection.
-func (t *tcpchanconn) SetTimeout(nsec int64) error {
- if err := t.SetReadTimeout(nsec); err != nil {
+func (t *tcpchanconn) SetDeadline(deadline time.Time) error {
+ if err := t.SetReadDeadline(deadline); err != nil {
return err
}
- return t.SetWriteTimeout(nsec)
+ return t.SetWriteDeadline(deadline)
}
-// SetReadTimeout sets the time (in nanoseconds) that
-// Read will wait for data before returning an error with Timeout() == true.
-// Setting nsec == 0 (the default) disables the deadline.
-func (t *tcpchanconn) SetReadTimeout(nsec int64) error {
- return errors.New("ssh: tcpchan: timeout not supported")
+// SetReadDeadline sets the read deadline.
+// A zero value for t means Read will not time out.
+// After the deadline, the error from Read will implement net.Error
+// with Timeout() == true.
+func (t *tcpchanconn) SetReadDeadline(deadline time.Time) error {
+ return errors.New("ssh: tcpchan: deadline not supported")
}
-// SetWriteTimeout sets the time (in nanoseconds) that
-// Write will wait to send its data before returning an error with Timeout() == true.
-// Setting nsec == 0 (the default) disables the deadline.
-// Even if write times out, it may return n > 0, indicating that
-// some of the data was successfully written.
-func (t *tcpchanconn) SetWriteTimeout(nsec int64) error {
- return errors.New("ssh: tcpchan: timeout not supported")
+// SetWriteDeadline exists to satisfy the net.Conn interface
+// but is not implemented by this type. It always returns an error.
+func (t *tcpchanconn) SetWriteDeadline(deadline time.Time) error {
+ return errors.New("ssh: tcpchan: deadline not supported")
}
diff --git a/src/pkg/log/syslog/syslog_test.go b/src/pkg/log/syslog/syslog_test.go
index 5c0b3e0c4e2..b9793e91abd 100644
--- a/src/pkg/log/syslog/syslog_test.go
+++ b/src/pkg/log/syslog/syslog_test.go
@@ -8,6 +8,7 @@ import (
"log"
"net"
"testing"
+ "time"
)
var serverAddr string
@@ -31,7 +32,7 @@ func startServer(done chan<- string) {
log.Fatalf("net.ListenPacket failed udp :0 %v", e)
}
serverAddr = c.LocalAddr().String()
- c.SetReadTimeout(100e6) // 100ms
+ c.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
go runSyslog(c, done)
}
diff --git a/src/pkg/net/dnsclient_unix.go b/src/pkg/net/dnsclient_unix.go
index 07e72ccb862..18c39360e40 100644
--- a/src/pkg/net/dnsclient_unix.go
+++ b/src/pkg/net/dnsclient_unix.go
@@ -45,7 +45,11 @@ func exchange(cfg *dnsConfig, c Conn, name string, qtype uint16) (*dnsMsg, error
return nil, err
}
- c.SetReadTimeout(int64(cfg.timeout) * 1e9) // nanoseconds
+ if cfg.timeout == 0 {
+ c.SetReadDeadline(time.Time{})
+ } else {
+ c.SetReadDeadline(time.Now().Add(time.Duration(cfg.timeout) * time.Second))
+ }
buf := make([]byte, 2000) // More than enough.
n, err = c.Read(buf)
diff --git a/src/pkg/net/fd.go b/src/pkg/net/fd.go
index 3dec9f4beb8..1b39cd7c4ba 100644
--- a/src/pkg/net/fd.go
+++ b/src/pkg/net/fd.go
@@ -33,12 +33,10 @@ type netFD struct {
raddr Addr
// owned by client
- rdeadline_delta int64
- rdeadline int64
- rio sync.Mutex
- wdeadline_delta int64
- wdeadline int64
- wio sync.Mutex
+ rdeadline int64
+ rio sync.Mutex
+ wdeadline int64
+ wio sync.Mutex
// owned by fd wait server
ncr, ncw int
@@ -388,11 +386,6 @@ func (fd *netFD) Read(p []byte) (n int, err error) {
if fd.sysfile == nil {
return 0, os.EINVAL
}
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
for {
n, err = syscall.Read(fd.sysfile.Fd(), p)
if err == syscall.EAGAIN {
@@ -423,11 +416,6 @@ func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
for {
n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
if err == syscall.EAGAIN {
@@ -456,11 +444,6 @@ func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.S
defer fd.rio.Unlock()
fd.incref()
defer fd.decref()
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
for {
n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
if err == syscall.EAGAIN {
@@ -493,11 +476,6 @@ func (fd *netFD) Write(p []byte) (n int, err error) {
if fd.sysfile == nil {
return 0, os.EINVAL
}
- if fd.wdeadline_delta > 0 {
- fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
- } else {
- fd.wdeadline = 0
- }
nn := 0
for {
@@ -539,11 +517,6 @@ func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
- if fd.wdeadline_delta > 0 {
- fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
- } else {
- fd.wdeadline = 0
- }
for {
err = syscall.Sendto(fd.sysfd, p, 0, sa)
if err == syscall.EAGAIN {
@@ -571,11 +544,6 @@ func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oob
defer fd.wio.Unlock()
fd.incref()
defer fd.decref()
- if fd.wdeadline_delta > 0 {
- fd.wdeadline = pollserver.Now() + fd.wdeadline_delta
- } else {
- fd.wdeadline = 0
- }
for {
err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
if err == syscall.EAGAIN {
@@ -603,11 +571,6 @@ func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (nfd *netFD, err err
fd.incref()
defer fd.decref()
- if fd.rdeadline_delta > 0 {
- fd.rdeadline = pollserver.Now() + fd.rdeadline_delta
- } else {
- fd.rdeadline = 0
- }
// See ../syscall/exec.go for description of ForkLock.
// It is okay to hold the lock across syscall.Accept
diff --git a/src/pkg/net/fd_windows.go b/src/pkg/net/fd_windows.go
index 7bffd1ca2fb..9e799bde9ff 100644
--- a/src/pkg/net/fd_windows.go
+++ b/src/pkg/net/fd_windows.go
@@ -150,12 +150,13 @@ func (s *ioSrv) ProcessRemoteIO() {
}
// ExecIO executes a single io operation. It either executes it
-// inline, or, if timeouts are employed, passes the request onto
+// inline, or, if a deadline is employed, passes the request onto
// a special goroutine and waits for completion or cancels request.
-func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
+// deadline is unix nanos.
+func (s *ioSrv) ExecIO(oi anOpIface, deadline int64) (n int, err error) {
var e error
o := oi.Op()
- if deadline_delta > 0 {
+ if deadline != 0 {
// Send request to a special dedicated thread,
// so it can stop the io with CancelIO later.
s.submchan <- oi
@@ -172,12 +173,17 @@ func (s *ioSrv) ExecIO(oi anOpIface, deadline_delta int64) (n int, err error) {
return 0, &OpError{oi.Name(), o.fd.net, o.fd.laddr, e}
}
// Wait for our request to complete.
- // TODO(rsc): This should stop the timer.
var r ioResult
- if deadline_delta > 0 {
+ if deadline != 0 {
+ dt := deadline - time.Now().UnixNano()
+ if dt < 1 {
+ dt = 1
+ }
+ ticker := time.NewTicker(time.Duration(dt) * time.Nanosecond)
+ defer ticker.Stop()
select {
case r = <-o.resultc:
- case <-time.After(time.Duration(deadline_delta) * time.Nanosecond):
+ case <-ticker.C:
s.canchan <- oi
<-o.errnoc
r = <-o.resultc
@@ -232,12 +238,10 @@ type netFD struct {
errnoc [2]chan error // read/write submit or cancel operation errors
// owned by client
- rdeadline_delta int64
- rdeadline int64
- rio sync.Mutex
- wdeadline_delta int64
- wdeadline int64
- wio sync.Mutex
+ rdeadline int64
+ rio sync.Mutex
+ wdeadline int64
+ wio sync.Mutex
}
func allocFD(fd syscall.Handle, family, proto int, net string) (f *netFD) {
@@ -357,7 +361,7 @@ func (fd *netFD) Read(buf []byte) (n int, err error) {
}
var o readOp
o.Init(fd, buf, 'r')
- n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
+ n, err = iosrv.ExecIO(&o, fd.rdeadline)
if err == nil && n == 0 {
err = io.EOF
}
@@ -398,7 +402,7 @@ func (fd *netFD) ReadFrom(buf []byte) (n int, sa syscall.Sockaddr, err error) {
var o readFromOp
o.Init(fd, buf, 'r')
o.rsan = int32(unsafe.Sizeof(o.rsa))
- n, err = iosrv.ExecIO(&o, fd.rdeadline_delta)
+ n, err = iosrv.ExecIO(&o, fd.rdeadline)
if err != nil {
return 0, nil, err
}
@@ -434,7 +438,7 @@ func (fd *netFD) Write(buf []byte) (n int, err error) {
}
var o writeOp
o.Init(fd, buf, 'w')
- return iosrv.ExecIO(&o, fd.wdeadline_delta)
+ return iosrv.ExecIO(&o, fd.wdeadline)
}
// WriteTo to network.
@@ -470,7 +474,7 @@ func (fd *netFD) WriteTo(buf []byte, sa syscall.Sockaddr) (n int, err error) {
var o writeToOp
o.Init(fd, buf, 'w')
o.sa = sa
- return iosrv.ExecIO(&o, fd.wdeadline_delta)
+ return iosrv.ExecIO(&o, fd.wdeadline)
}
// Accept new network connections.
diff --git a/src/pkg/net/http/httputil/dump.go b/src/pkg/net/http/httputil/dump.go
index 61b18ffb1c6..b8a98ee4292 100644
--- a/src/pkg/net/http/httputil/dump.go
+++ b/src/pkg/net/http/httputil/dump.go
@@ -13,6 +13,7 @@ import (
"net"
"net/http"
"strings"
+ "time"
)
// One of the copies, say from b to r2, could be avoided by using a more
@@ -36,12 +37,12 @@ type dumpConn struct {
io.Reader
}
-func (c *dumpConn) Close() error { return nil }
-func (c *dumpConn) LocalAddr() net.Addr { return nil }
-func (c *dumpConn) RemoteAddr() net.Addr { return nil }
-func (c *dumpConn) SetTimeout(nsec int64) error { return nil }
-func (c *dumpConn) SetReadTimeout(nsec int64) error { return nil }
-func (c *dumpConn) SetWriteTimeout(nsec int64) error { return nil }
+func (c *dumpConn) Close() error { return nil }
+func (c *dumpConn) LocalAddr() net.Addr { return nil }
+func (c *dumpConn) RemoteAddr() net.Addr { return nil }
+func (c *dumpConn) SetDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetReadDeadline(t time.Time) error { return nil }
+func (c *dumpConn) SetWriteDeadline(t time.Time) error { return nil }
// DumpRequestOut is like DumpRequest but includes
// headers that the standard http.Transport adds,
diff --git a/src/pkg/net/http/serve_test.go b/src/pkg/net/http/serve_test.go
index 265cb2761a3..9aff467eedb 100644
--- a/src/pkg/net/http/serve_test.go
+++ b/src/pkg/net/http/serve_test.go
@@ -84,15 +84,15 @@ func (c *testConn) RemoteAddr() net.Addr {
return dummyAddr("remote-addr")
}
-func (c *testConn) SetTimeout(nsec int64) error {
+func (c *testConn) SetDeadline(t time.Time) error {
return nil
}
-func (c *testConn) SetReadTimeout(nsec int64) error {
+func (c *testConn) SetReadDeadline(t time.Time) error {
return nil
}
-func (c *testConn) SetWriteTimeout(nsec int64) error {
+func (c *testConn) SetWriteDeadline(t time.Time) error {
return nil
}
diff --git a/src/pkg/net/http/server.go b/src/pkg/net/http/server.go
index fa9009517db..22ea8e31720 100644
--- a/src/pkg/net/http/server.go
+++ b/src/pkg/net/http/server.go
@@ -954,8 +954,8 @@ func Serve(l net.Listener, handler Handler) error {
type Server struct {
Addr string // TCP address to listen on, ":http" if empty
Handler Handler // handler to invoke, http.DefaultServeMux if nil
- ReadTimeout time.Duration // the net.Conn.SetReadTimeout value for new connections
- WriteTimeout time.Duration // the net.Conn.SetWriteTimeout value for new connections
+ ReadTimeout time.Duration // maximum duration before timing out read of the request
+ WriteTimeout time.Duration // maximum duration before timing out write of the response
MaxHeaderBytes int // maximum size of request headers, DefaultMaxHeaderBytes if 0
}
@@ -989,10 +989,10 @@ func (srv *Server) Serve(l net.Listener) error {
return e
}
if srv.ReadTimeout != 0 {
- rw.SetReadTimeout(srv.ReadTimeout.Nanoseconds())
+ rw.SetReadDeadline(time.Now().Add(srv.ReadTimeout))
}
if srv.WriteTimeout != 0 {
- rw.SetWriteTimeout(srv.WriteTimeout.Nanoseconds())
+ rw.SetWriteDeadline(time.Now().Add(srv.WriteTimeout))
}
c, err := srv.newConn(rw)
if err != nil {
diff --git a/src/pkg/net/ipraw_test.go b/src/pkg/net/ipraw_test.go
index 67a4049d5d3..c74bfcd6c79 100644
--- a/src/pkg/net/ipraw_test.go
+++ b/src/pkg/net/ipraw_test.go
@@ -12,6 +12,7 @@ import (
"flag"
"os"
"testing"
+ "time"
)
const ICMP_ECHO_REQUEST = 8
@@ -101,7 +102,7 @@ func TestICMP(t *testing.T) {
t.Fatalf(`net.WriteToIP(..., %v) = %v, %v`, raddr, n, err)
}
- c.SetTimeout(100e6)
+ c.SetDeadline(time.Now().Add(100 * time.Millisecond))
resp := make([]byte, 1024)
for {
n, from, err := c.ReadFrom(resp)
diff --git a/src/pkg/net/iprawsock_posix.go b/src/pkg/net/iprawsock_posix.go
index 103c4f6a925..e4f755bc785 100644
--- a/src/pkg/net/iprawsock_posix.go
+++ b/src/pkg/net/iprawsock_posix.go
@@ -12,6 +12,7 @@ import (
"errors"
"os"
"syscall"
+ "time"
)
func sockaddrToIP(sa syscall.Sockaddr) Addr {
@@ -97,28 +98,28 @@ func (c *IPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *IPConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *IPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *IPConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *IPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *IPConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *IPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -146,8 +147,8 @@ func (c *IPConn) SetWriteBuffer(bytes int) error {
// that was on the packet.
//
// ReadFromIP can be made to time out and return an error with
-// Timeout() == true after a fixed time limit; see SetTimeout and
-// SetReadTimeout.
+// Timeout() == true after a fixed time limit; see SetDeadline and
+// SetReadDeadline.
func (c *IPConn) ReadFromIP(b []byte) (n int, addr *IPAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -182,7 +183,7 @@ func (c *IPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToIP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *IPConn) WriteToIP(b []byte, addr *IPAddr) (n int, err error) {
if !c.ok() {
diff --git a/src/pkg/net/net.go b/src/pkg/net/net.go
index b236dfdb1dd..7db7dfd1343 100644
--- a/src/pkg/net/net.go
+++ b/src/pkg/net/net.go
@@ -9,7 +9,10 @@ package net
// TODO(rsc):
// support for raw ethernet sockets
-import "errors"
+import (
+ "errors"
+ "time"
+)
// Addr represents a network end point address.
type Addr interface {
@@ -38,21 +41,23 @@ type Conn interface {
// RemoteAddr returns the remote network address.
RemoteAddr() Addr
- // SetTimeout sets the read and write deadlines associated
+ // SetDeadline sets the read and write deadlines associated
// with the connection.
- SetTimeout(nsec int64) error
+ SetDeadline(t time.Time) error
- // SetReadTimeout sets the time (in nanoseconds) that
- // Read will wait for data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
- SetReadTimeout(nsec int64) error
+ // SetReadDeadline sets the deadline for all Read calls to return.
+ // If the deadline is reached, Read will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Read will not time out.
+ SetReadDeadline(t time.Time) error
- // SetWriteTimeout sets the time (in nanoseconds) that
- // Write will wait to send its data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
+ // SetWriteDeadline sets the deadline for all Write calls to return.
+ // If the deadline is reached, Write will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Write will not time out.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
- SetWriteTimeout(nsec int64) error
+ SetWriteDeadline(t time.Time) error
}
// An Error represents a network error.
@@ -70,13 +75,13 @@ type PacketConn interface {
// was on the packet.
// ReadFrom can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
- // see SetTimeout and SetReadTimeout.
+ // see SetDeadline and SetReadDeadline.
ReadFrom(b []byte) (n int, addr Addr, err error)
// WriteTo writes a packet with payload b to addr.
// WriteTo can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
- // see SetTimeout and SetWriteTimeout.
+ // see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
WriteTo(b []byte, addr Addr) (n int, err error)
@@ -86,21 +91,23 @@ type PacketConn interface {
// LocalAddr returns the local network address.
LocalAddr() Addr
- // SetTimeout sets the read and write deadlines associated
+ // SetDeadline sets the read and write deadlines associated
// with the connection.
- SetTimeout(nsec int64) error
+ SetDeadline(t time.Time) error
- // SetReadTimeout sets the time (in nanoseconds) that
- // Read will wait for data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
- SetReadTimeout(nsec int64) error
+ // SetReadDeadline sets the deadline for all Read calls to return.
+ // If the deadline is reached, Read will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Read will not time out.
+ SetReadDeadline(t time.Time) error
- // SetWriteTimeout sets the time (in nanoseconds) that
- // Write will wait to send its data before returning an error with Timeout() == true.
- // Setting nsec == 0 (the default) disables the deadline.
+ // SetWriteDeadline sets the deadline for all Write calls to return.
+ // If the deadline is reached, Write will fail with a timeout
+ // (see type Error) instead of blocking.
+ // A zero value for t means Write will not time out.
// Even if write times out, it may return n > 0, indicating that
// some of the data was successfully written.
- SetWriteTimeout(nsec int64) error
+ SetWriteDeadline(t time.Time) error
}
// A Listener is a generic network listener for stream-oriented protocols.
diff --git a/src/pkg/net/pipe.go b/src/pkg/net/pipe.go
index 0ce7ccb9d7b..f1a2eca4e88 100644
--- a/src/pkg/net/pipe.go
+++ b/src/pkg/net/pipe.go
@@ -7,6 +7,7 @@ package net
import (
"errors"
"io"
+ "time"
)
// Pipe creates a synchronous, in-memory, full duplex
@@ -53,14 +54,14 @@ func (p *pipe) RemoteAddr() Addr {
return pipeAddr(0)
}
-func (p *pipe) SetTimeout(nsec int64) error {
- return errors.New("net.Pipe does not support timeouts")
+func (p *pipe) SetDeadline(t time.Time) error {
+ return errors.New("net.Pipe does not support deadlines")
}
-func (p *pipe) SetReadTimeout(nsec int64) error {
- return errors.New("net.Pipe does not support timeouts")
+func (p *pipe) SetReadDeadline(t time.Time) error {
+ return errors.New("net.Pipe does not support deadlines")
}
-func (p *pipe) SetWriteTimeout(nsec int64) error {
- return errors.New("net.Pipe does not support timeouts")
+func (p *pipe) SetWriteDeadline(t time.Time) error {
+ return errors.New("net.Pipe does not support deadlines")
}
diff --git a/src/pkg/net/sendfile_linux.go b/src/pkg/net/sendfile_linux.go
index 350abe451f3..e9ab066663e 100644
--- a/src/pkg/net/sendfile_linux.go
+++ b/src/pkg/net/sendfile_linux.go
@@ -40,15 +40,6 @@ func sendFile(c *netFD, r io.Reader) (written int64, err error, handled bool) {
defer c.wio.Unlock()
c.incref()
defer c.decref()
- if c.wdeadline_delta > 0 {
- // This is a little odd that we're setting the timeout
- // for the entire file but Write has the same issue
- // (if one slurps the whole file into memory and
- // do one large Write). At least they're consistent.
- c.wdeadline = pollserver.Now() + c.wdeadline_delta
- } else {
- c.wdeadline = 0
- }
dst := c.sysfd
src := f.Fd()
diff --git a/src/pkg/net/server_test.go b/src/pkg/net/server_test.go
index 29d2532a1ed..b0b546be32b 100644
--- a/src/pkg/net/server_test.go
+++ b/src/pkg/net/server_test.go
@@ -11,6 +11,7 @@ import (
"runtime"
"strings"
"testing"
+ "time"
)
// Do not test empty datagrams by default.
@@ -63,7 +64,7 @@ func connect(t *testing.T, network, addr string, isEmpty bool) {
if err != nil {
t.Fatalf("net.Dial(%q, %q) = _, %v", network, addr, err)
}
- fd.SetReadTimeout(1e9) // 1s
+ fd.SetReadDeadline(time.Now().Add(1 * time.Second))
var b []byte
if !isEmpty {
@@ -169,10 +170,10 @@ func runPacket(t *testing.T, network, addr string, listening chan<- string, done
t.Fatalf("net.ListenPacket(%q, %q) = _, %v", network, addr, err)
}
listening <- c.LocalAddr().String()
- c.SetReadTimeout(10e6) // 10ms
var buf [1000]byte
Run:
for {
+ c.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
n, addr, err := c.ReadFrom(buf[0:])
if e, ok := err.(Error); ok && e.Timeout() {
select {
diff --git a/src/pkg/net/sockopt.go b/src/pkg/net/sockopt.go
index 7fa1052b120..59f9af5f30a 100644
--- a/src/pkg/net/sockopt.go
+++ b/src/pkg/net/sockopt.go
@@ -12,6 +12,7 @@ import (
"bytes"
"os"
"syscall"
+ "time"
)
// Boolean to int.
@@ -115,21 +116,21 @@ func setWriteBuffer(fd *netFD, bytes int) error {
return os.NewSyscallError("setsockopt", syscall.SetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_SNDBUF, bytes))
}
-func setReadTimeout(fd *netFD, nsec int64) error {
- fd.rdeadline_delta = nsec
+func setReadDeadline(fd *netFD, t time.Time) error {
+ fd.rdeadline = t.UnixNano()
return nil
}
-func setWriteTimeout(fd *netFD, nsec int64) error {
- fd.wdeadline_delta = nsec
+func setWriteDeadline(fd *netFD, t time.Time) error {
+ fd.wdeadline = t.UnixNano()
return nil
}
-func setTimeout(fd *netFD, nsec int64) error {
- if e := setReadTimeout(fd, nsec); e != nil {
+func setDeadline(fd *netFD, t time.Time) error {
+ if e := setReadDeadline(fd, t); e != nil {
return e
}
- return setWriteTimeout(fd, nsec)
+ return setWriteDeadline(fd, t)
}
func setReuseAddr(fd *netFD, reuse bool) error {
diff --git a/src/pkg/net/tcpsock_posix.go b/src/pkg/net/tcpsock_posix.go
index a492e614e35..91816fa9d46 100644
--- a/src/pkg/net/tcpsock_posix.go
+++ b/src/pkg/net/tcpsock_posix.go
@@ -12,6 +12,7 @@ import (
"io"
"os"
"syscall"
+ "time"
)
// BUG(rsc): On OpenBSD, listening on the "tcp" network does not listen for
@@ -134,28 +135,28 @@ func (c *TCPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *TCPConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *TCPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *TCPConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *TCPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *TCPConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *TCPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -294,12 +295,13 @@ func (l *TCPListener) Close() error {
// Addr returns the listener's network address, a *TCPAddr.
func (l *TCPListener) Addr() Addr { return l.fd.laddr }
-// SetTimeout sets the deadline associated with the listener
-func (l *TCPListener) SetTimeout(nsec int64) error {
+// SetDeadline sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *TCPListener) SetDeadline(t time.Time) error {
if l == nil || l.fd == nil {
return os.EINVAL
}
- return setTimeout(l.fd, nsec)
+ return setDeadline(l.fd, t)
}
// File returns a copy of the underlying os.File, set to blocking mode.
diff --git a/src/pkg/net/timeout_test.go b/src/pkg/net/timeout_test.go
index f6e5238c1b1..11db012ff57 100644
--- a/src/pkg/net/timeout_test.go
+++ b/src/pkg/net/timeout_test.go
@@ -5,6 +5,7 @@
package net
import (
+ "fmt"
"runtime"
"testing"
"time"
@@ -17,26 +18,41 @@ func testTimeout(t *testing.T, network, addr string, readFrom bool) {
return
}
defer fd.Close()
- t0 := time.Now()
- fd.SetReadTimeout(1e8) // 100ms
- var b [100]byte
- var n int
- var err1 error
- if readFrom {
- n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
- } else {
- n, err1 = fd.Read(b[0:])
- }
- t1 := time.Now()
what := "Read"
if readFrom {
what = "ReadFrom"
}
- if n != 0 || err1 == nil || !err1.(Error).Timeout() {
- t.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
- }
- if dt := t1.Sub(t0); dt < 50*time.Millisecond || dt > 150*time.Millisecond {
- t.Errorf("fd.%s on %s %s took %s, expected 0.1s", what, network, addr, dt)
+
+ errc := make(chan error, 1)
+ go func() {
+ t0 := time.Now()
+ fd.SetReadDeadline(time.Now().Add(100 * time.Millisecond))
+ var b [100]byte
+ var n int
+ var err1 error
+ if readFrom {
+ n, _, err1 = fd.(PacketConn).ReadFrom(b[0:])
+ } else {
+ n, err1 = fd.Read(b[0:])
+ }
+ t1 := time.Now()
+ if n != 0 || err1 == nil || !err1.(Error).Timeout() {
+ errc <- fmt.Errorf("fd.%s on %s %s did not return 0, timeout: %v, %v", what, network, addr, n, err1)
+ return
+ }
+ if dt := t1.Sub(t0); dt < 50*time.Millisecond || dt > 250*time.Millisecond {
+ errc <- fmt.Errorf("fd.%s on %s %s took %s, expected 0.1s", what, network, addr, dt)
+ return
+ }
+ errc <- nil
+ }()
+ select {
+ case err := <-errc:
+ if err != nil {
+ t.Error(err)
+ }
+ case <-time.After(1 * time.Second):
+ t.Errorf("%s on %s %s took over 1 second, expected 0.1s", what, network, addr)
}
}
diff --git a/src/pkg/net/udpsock_posix.go b/src/pkg/net/udpsock_posix.go
index d0bdb14755e..0b5bc16f822 100644
--- a/src/pkg/net/udpsock_posix.go
+++ b/src/pkg/net/udpsock_posix.go
@@ -11,6 +11,7 @@ package net
import (
"os"
"syscall"
+ "time"
)
func sockaddrToUDP(sa syscall.Sockaddr) Addr {
@@ -98,28 +99,28 @@ func (c *UDPConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UDPConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UDPConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UDPConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UDPConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UDPConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UDPConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -147,7 +148,7 @@ func (c *UDPConn) SetWriteBuffer(bytes int) error {
// that was on the packet.
//
// ReadFromUDP can be made to time out and return an error with Timeout() == true
-// after a fixed time limit; see SetTimeout and SetReadTimeout.
+// after a fixed time limit; see SetDeadline and SetReadDeadline.
func (c *UDPConn) ReadFromUDP(b []byte) (n int, addr *UDPAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -175,7 +176,7 @@ func (c *UDPConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToUDP can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (n int, err error) {
if !c.ok() {
diff --git a/src/pkg/net/unixsock_posix.go b/src/pkg/net/unixsock_posix.go
index 00ee0164f2e..2f8ff19e7ff 100644
--- a/src/pkg/net/unixsock_posix.go
+++ b/src/pkg/net/unixsock_posix.go
@@ -11,6 +11,7 @@ package net
import (
"os"
"syscall"
+ "time"
)
func unixSocket(net string, laddr, raddr *UnixAddr, mode string) (fd *netFD, err error) {
@@ -164,28 +165,28 @@ func (c *UnixConn) RemoteAddr() Addr {
return c.fd.raddr
}
-// SetTimeout implements the net.Conn SetTimeout method.
-func (c *UnixConn) SetTimeout(nsec int64) error {
+// SetDeadline implements the net.Conn SetDeadline method.
+func (c *UnixConn) SetDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setTimeout(c.fd, nsec)
+ return setDeadline(c.fd, t)
}
-// SetReadTimeout implements the net.Conn SetReadTimeout method.
-func (c *UnixConn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline implements the net.Conn SetReadDeadline method.
+func (c *UnixConn) SetReadDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setReadTimeout(c.fd, nsec)
+ return setReadDeadline(c.fd, t)
}
-// SetWriteTimeout implements the net.Conn SetWriteTimeout method.
-func (c *UnixConn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline implements the net.Conn SetWriteDeadline method.
+func (c *UnixConn) SetWriteDeadline(t time.Time) error {
if !c.ok() {
return os.EINVAL
}
- return setWriteTimeout(c.fd, nsec)
+ return setWriteDeadline(c.fd, t)
}
// SetReadBuffer sets the size of the operating system's
@@ -212,7 +213,7 @@ func (c *UnixConn) SetWriteBuffer(bytes int) error {
//
// ReadFromUnix can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetReadTimeout.
+// see SetDeadline and SetReadDeadline.
func (c *UnixConn) ReadFromUnix(b []byte) (n int, addr *UnixAddr, err error) {
if !c.ok() {
return 0, nil, os.EINVAL
@@ -238,7 +239,7 @@ func (c *UnixConn) ReadFrom(b []byte) (n int, addr Addr, err error) {
//
// WriteToUnix can be made to time out and return
// an error with Timeout() == true after a fixed time limit;
-// see SetTimeout and SetWriteTimeout.
+// see SetDeadline and SetWriteDeadline.
// On packet-oriented connections, write timeouts are rare.
func (c *UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (n int, err error) {
if !c.ok() {
@@ -386,12 +387,13 @@ func (l *UnixListener) Close() error {
// Addr returns the listener's network address.
func (l *UnixListener) Addr() Addr { return l.fd.laddr }
-// SetTimeout sets the deadline associated wuth the listener
-func (l *UnixListener) SetTimeout(nsec int64) (err error) {
+// SetTimeout sets the deadline associated with the listener.
+// A zero time value disables the deadline.
+func (l *UnixListener) SetDeadline(t time.Time) (err error) {
if l == nil || l.fd == nil {
return os.EINVAL
}
- return setTimeout(l.fd, nsec)
+ return setDeadline(l.fd, t)
}
// File returns a copy of the underlying os.File, set to blocking mode.
diff --git a/src/pkg/websocket/websocket.go b/src/pkg/websocket/websocket.go
index df4416e22ed..f7aabc94b35 100644
--- a/src/pkg/websocket/websocket.go
+++ b/src/pkg/websocket/websocket.go
@@ -17,6 +17,7 @@ import (
"net/http"
"net/url"
"sync"
+ "time"
)
const (
@@ -243,30 +244,30 @@ func (ws *Conn) RemoteAddr() net.Addr {
return &Addr{ws.config.Origin}
}
-var errSetTimeout = errors.New("websocket: cannot set timeout: not using a net.Conn")
+var errSetDeadline = errors.New("websocket: cannot set deadline: not using a net.Conn")
-// SetTimeout sets the connection's network timeout in nanoseconds.
-func (ws *Conn) SetTimeout(nsec int64) error {
+// SetDeadline sets the connection's network read & write deadlines.
+func (ws *Conn) SetDeadline(t time.Time) error {
if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetTimeout(nsec)
+ return conn.SetDeadline(t)
}
- return errSetTimeout
+ return errSetDeadline
}
-// SetReadTimeout sets the connection's network read timeout in nanoseconds.
-func (ws *Conn) SetReadTimeout(nsec int64) error {
+// SetReadDeadline sets the connection's network read deadline.
+func (ws *Conn) SetReadDeadline(t time.Time) error {
if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetReadTimeout(nsec)
+ return conn.SetReadDeadline(t)
}
- return errSetTimeout
+ return errSetDeadline
}
-// SetWriteTimeout sets the connection's network write timeout in nanoseconds.
-func (ws *Conn) SetWriteTimeout(nsec int64) error {
+// SetWriteDeadline sets the connection's network write deadline.
+func (ws *Conn) SetWriteDeadline(t time.Time) error {
if conn, ok := ws.rwc.(net.Conn); ok {
- return conn.SetWriteTimeout(nsec)
+ return conn.SetWriteDeadline(t)
}
- return errSetTimeout
+ return errSetDeadline
}
// Config returns the WebSocket config.