diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 97531f944..05c82a478 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -48,7 +48,7 @@ jobs: - name: Setup and run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.52.2 + version: v1.55.2 args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot --timeout 5m test: needs: lint diff --git a/.github/workflows/test_gc_opt.yml b/.github/workflows/test_gc_opt.yml index 318736650..b277b3c40 100644 --- a/.github/workflows/test_gc_opt.yml +++ b/.github/workflows/test_gc_opt.yml @@ -48,7 +48,7 @@ jobs: - name: Setup and run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.52.2 + version: v1.55.2 args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot --timeout 5m test: needs: lint diff --git a/.github/workflows/test_poll_opt.yml b/.github/workflows/test_poll_opt.yml index 53f908da1..62aeee86f 100644 --- a/.github/workflows/test_poll_opt.yml +++ b/.github/workflows/test_poll_opt.yml @@ -47,7 +47,7 @@ jobs: - name: Setup and run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.52.2 + version: v1.55.2 args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot test: needs: lint diff --git a/.github/workflows/test_poll_opt_gc_opt.yml b/.github/workflows/test_poll_opt_gc_opt.yml index e4d8f2565..5e5cedfe8 100644 --- a/.github/workflows/test_poll_opt_gc_opt.yml +++ b/.github/workflows/test_poll_opt_gc_opt.yml @@ -47,7 +47,7 @@ jobs: - name: Setup and run golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.52.2 + version: v1.55.2 args: -v -E gofumpt -E gocritic -E misspell -E revive -E godot test: needs: lint diff --git a/go.mod b/go.mod index 1366f70b4..ab7e010c5 100644 --- a/go.mod +++ b/go.mod @@ -5,8 +5,8 @@ require ( github.com/stretchr/testify v1.8.4 github.com/valyala/bytebufferpool v1.0.0 go.uber.org/zap v1.21.0 - golang.org/x/sync v0.3.0 - golang.org/x/sys v0.12.0 + golang.org/x/sync v0.5.0 + golang.org/x/sys v0.15.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) diff --git a/go.sum b/go.sum index 06de6e794..8e3704477 100644 --- a/go.sum +++ b/go.sum @@ -45,15 +45,16 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= diff --git a/internal/socket/sockopts_darwin.go b/internal/socket/sockopts_darwin.go index b64adf0e4..338857cc5 100644 --- a/internal/socket/sockopts_darwin.go +++ b/internal/socket/sockopts_darwin.go @@ -27,13 +27,28 @@ func SetKeepAlivePeriod(fd, secs int) error { if secs <= 0 { return errors.New("invalid time duration") } - if err := os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1)); err != nil { - return err + + if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { + return os.NewSyscallError("setsockopt", err) + } + + if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, secs); err != nil { + return os.NewSyscallError("setsockopt", err) } - switch err := os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, secs)); err { - case nil, unix.ENOPROTOOPT: // OS X 10.7 and earlier don't support this option - default: - return err + + interval := secs / 5 + if interval == 0 { + interval = 1 + } + if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, interval); err != nil { + // In earlier versions, macOS only supported setting TCP_KEEPALIVE (the equivalent of TCP_KEEPIDLE on other platforms), + // but since macOS 10.8 it has supported TCP_KEEPINTVL and TCP_KEEPCNT. + // If the current OS is macOS and the error is ENOPROTOOPT, ignore it. + if err == unix.ENOPROTOOPT { + err = nil + } + return os.NewSyscallError("setsockopt", err) } - return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPALIVE, secs)) + + return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPCNT, 5)) } diff --git a/internal/socket/sockopts_openbsd.go b/internal/socket/sockopts_openbsd.go new file mode 100644 index 000000000..8670f2af0 --- /dev/null +++ b/internal/socket/sockopts_openbsd.go @@ -0,0 +1,24 @@ +// Copyright (c) 2024 The Gnet Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package socket + +import "golang.org/x/sys/unix" + +// SetKeepAlivePeriod sets whether the operating system should send +// keep-alive messages on the connection and sets period between TCP keep-alive probes. +func SetKeepAlivePeriod(_, _ int) error { + // OpenBSD has no user-settable per-socket TCP keepalive options. + return unix.ENOPROTOOPT +} diff --git a/internal/socket/sockopts_unix.go b/internal/socket/sockopts_unix.go index 95184a12a..1d1a2d559 100644 --- a/internal/socket/sockopts_unix.go +++ b/internal/socket/sockopts_unix.go @@ -12,8 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//go:build linux || freebsd || dragonfly || netbsd || openbsd -// +build linux freebsd dragonfly netbsd openbsd +//go:build linux || freebsd || dragonfly || netbsd +// +build linux freebsd dragonfly netbsd package socket @@ -30,11 +30,22 @@ func SetKeepAlivePeriod(fd, secs int) error { if secs <= 0 { return errors.New("invalid time duration") } - if err := os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1)); err != nil { - return err + + if err := unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_KEEPALIVE, 1); err != nil { + return os.NewSyscallError("setsockopt", err) + } + + if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPIDLE, secs); err != nil { + return os.NewSyscallError("setsockopt", err) } - if err := os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, secs)); err != nil { - return err + + interval := secs / 5 + if interval == 0 { + interval = 1 + } + if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPINTVL, interval); err != nil { + return os.NewSyscallError("setsockopt", err) } - return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPIDLE, secs)) + + return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_KEEPCNT, 5)) }