Skip to content

Commit eee43bd

Browse files
committed
net: enable TCP keepalives by default
This is just the first step in attempting to make all network connection have timeouts as a "safe default". TCP keepalives only protect against certain classes of network and host issues (e.g. server/OS crash), but do nothing against application-level issues (e.g. an application that accepts connections but then fails to serve requests). The actual keep-alive duration (15s) is chosen to cause broken connections to be closed after 2~3 minutes (depending on the OS, see golang#23549 for details). We don't make the actual default value part of the public API for a number of reasons: - because it's not very useful by itself: as discussed in golang#23549 the actual "timeout" after which the connection is torn down is duration*(KEEPCNT+1), and we use the OS-wide value for KEEPCNT because there's currently no way to set it from Go. - because it may change in the future: if users need to rely on a specific value they should explicitly set this value instead of relying on the default. Fixes golang#23459 Change-Id: I348c03be97588d5001e6de0f377e7a93b51957fd
1 parent b61b1d2 commit eee43bd

File tree

3 files changed

+32
-16
lines changed

3 files changed

+32
-16
lines changed

src/net/dial.go

+10-4
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,10 @@ type Dialer struct {
5757

5858
// KeepAlive specifies the keep-alive period for an active
5959
// network connection.
60-
// If zero, keep-alives are not enabled. Network protocols
60+
// If zero, keep-alives are enabled if supported by the protocol
61+
// and operating system. Network protocols or operating systems
6162
// that do not support keep-alives ignore this field.
63+
// If negative, keep-alives are disabled.
6264
KeepAlive time.Duration
6365

6466
// Resolver optionally specifies an alternate resolver to use.
@@ -400,10 +402,14 @@ func (d *Dialer) DialContext(ctx context.Context, network, address string) (Conn
400402
return nil, err
401403
}
402404

403-
if tc, ok := c.(*TCPConn); ok && d.KeepAlive > 0 {
405+
if tc, ok := c.(*TCPConn); ok && d.KeepAlive >= 0 {
404406
setKeepAlive(tc.fd, true)
405-
setKeepAlivePeriod(tc.fd, d.KeepAlive)
406-
testHookSetKeepAlive()
407+
ka := d.KeepAlive
408+
if d.KeepAlive == 0 {
409+
ka = 15 * time.Second
410+
}
411+
setKeepAlivePeriod(tc.fd, ka)
412+
testHookSetKeepAlive(ka)
407413
}
408414
return c, nil
409415
}

src/net/dial_test.go

+17-10
Original file line numberDiff line numberDiff line change
@@ -725,22 +725,29 @@ func TestDialerKeepAlive(t *testing.T) {
725725
if err := ls.buildup(handler); err != nil {
726726
t.Fatal(err)
727727
}
728-
defer func() { testHookSetKeepAlive = func() {} }()
728+
defer func() { testHookSetKeepAlive = func(time.Duration) {} }()
729729

730-
for _, keepAlive := range []bool{false, true} {
731-
got := false
732-
testHookSetKeepAlive = func() { got = true }
733-
var d Dialer
734-
if keepAlive {
735-
d.KeepAlive = 30 * time.Second
736-
}
730+
tests := []struct {
731+
ka time.Duration
732+
expected time.Duration
733+
}{
734+
{-1, -1},
735+
{0, 15 * time.Second},
736+
{5 * time.Second, 5 * time.Second},
737+
{30 * time.Second, 30 * time.Second},
738+
}
739+
740+
for _, test := range tests {
741+
var got time.Duration = -1
742+
testHookSetKeepAlive = func(d time.Duration) { got = d }
743+
d := Dialer{KeepAlive: test.ka}
737744
c, err := d.Dial("tcp", ls.Listener.Addr().String())
738745
if err != nil {
739746
t.Fatal(err)
740747
}
741748
c.Close()
742-
if got != keepAlive {
743-
t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive called = %v, want %v", d.KeepAlive, got, !got)
749+
if got != test.expected {
750+
t.Errorf("Dialer.KeepAlive = %v: SetKeepAlive set to %v, want %v", d.KeepAlive, got, test.expected)
744751
}
745752
}
746753
}

src/net/hook.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44

55
package net
66

7-
import "context"
7+
import (
8+
"context"
9+
"time"
10+
)
811

912
var (
1013
// if non-nil, overrides dialTCP.
@@ -18,5 +21,5 @@ var (
1821
) ([]IPAddr, error) {
1922
return fn(ctx, host)
2023
}
21-
testHookSetKeepAlive = func() {}
24+
testHookSetKeepAlive = func(time.Duration) {}
2225
)

0 commit comments

Comments
 (0)