mirror of
https://github.com/google/gops.git
synced 2024-11-19 20:31:58 +02:00
agent: allow to set SO_REUSEPORT on listening socket
Introduce Option.SocketReuseAddrAndPort which, if set, will lead to the SO_REUSEPORT socket option being set on the listening socket on Unix-like OSes. This also sets SO_REUSEADDR which is already the default in net.Listen (see net.setDefaultSockopts). Setting these options increases the chance to re-bind() to the same address and port upon agent restart if Options.Addr is set. Signed-off-by: Tobias Klauser <tklauser@distanz.ch>
This commit is contained in:
parent
b55933ebc4
commit
268f11e4fc
@ -8,6 +8,7 @@ package agent
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -55,6 +56,13 @@ type Options struct {
|
||||
// can call Close before shutting down.
|
||||
// Optional.
|
||||
ShutdownCleanup bool
|
||||
|
||||
// ReuseSocketAddrAndPort determines whether the SO_REUSEADDR and
|
||||
// SO_REUSEADDR socket options should be set on the listening socket of
|
||||
// the agent. This option is only effective on unix-like OSes and if
|
||||
// Addr is set to a fixed host:port.
|
||||
// Optional.
|
||||
ReuseSocketAddrAndPort bool
|
||||
}
|
||||
|
||||
// Listen starts the gops agent on a host process. Once agent started, users
|
||||
@ -96,11 +104,14 @@ func Listen(opts Options) error {
|
||||
if addr == "" {
|
||||
addr = defaultAddr
|
||||
}
|
||||
ln, err := net.Listen("tcp", addr)
|
||||
var lc net.ListenConfig
|
||||
if opts.ReuseSocketAddrAndPort {
|
||||
lc.Control = setsockoptReuseAddrAndPort
|
||||
}
|
||||
listener, err = lc.Listen(context.Background(), "tcp", addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
listener = ln
|
||||
port := listener.Addr().(*net.TCPAddr).Port
|
||||
portfile = fmt.Sprintf("%s/%d", gopsdir, os.Getpid())
|
||||
err = ioutil.WriteFile(portfile, []byte(strconv.Itoa(port)), os.ModePerm)
|
||||
|
@ -54,6 +54,17 @@ func TestAgentListenMultipleClose(t *testing.T) {
|
||||
Close()
|
||||
}
|
||||
|
||||
func TestAgentListenReuseAddrAndPort(t *testing.T) {
|
||||
err := Listen(Options{
|
||||
Addr: "127.0.0.1:50000",
|
||||
ReuseSocketAddrAndPort: true,
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
Close()
|
||||
}
|
||||
|
||||
func TestFormatBytes(t *testing.T) {
|
||||
tests := []struct {
|
||||
val uint64
|
||||
|
36
agent/sockopt_unix.go
Normal file
36
agent/sockopt_unix.go
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// +build !js,!plan9,!windows
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
// setsockoptReuseAddrAndPort sets the SO_REUSEADDR and SO_REUSEPORT socket
|
||||
// options on c's underlying socket in order to increase the chance to re-bind()
|
||||
// to the same address and port upon agent restart.
|
||||
func setsockoptReuseAddrAndPort(network, address string, c syscall.RawConn) error {
|
||||
var soerr error
|
||||
if err := c.Control(func(su uintptr) {
|
||||
sock := int(su)
|
||||
// Allow reuse of recently-used addresses. This socket option is
|
||||
// set by default on listeners in Go's net package, see
|
||||
// net.setDefaultSockopts.
|
||||
soerr = unix.SetsockoptInt(sock, unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
|
||||
if soerr != nil {
|
||||
return
|
||||
}
|
||||
// Allow reuse of recently-used ports. This gives the agent a
|
||||
// better chance to re-bind upon restarts.
|
||||
soerr = unix.SetsockoptInt(sock, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
return soerr
|
||||
}
|
13
agent/sockopt_unsupported.go
Normal file
13
agent/sockopt_unsupported.go
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2020 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.
|
||||
|
||||
// +build js,wasm plan9 windows
|
||||
|
||||
package agent
|
||||
|
||||
import "syscall"
|
||||
|
||||
func setsockoptReuseAddrAndPort(network, address string, c syscall.RawConn) error {
|
||||
return nil
|
||||
}
|
2
go.mod
2
go.mod
@ -9,6 +9,6 @@ require (
|
||||
github.com/shirou/gopsutil v2.20.4+incompatible
|
||||
github.com/stretchr/testify v1.3.0 // indirect
|
||||
github.com/xlab/treeprint v1.0.0
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 // indirect
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d
|
||||
rsc.io/goversion v1.2.0
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@ -15,7 +15,7 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/xlab/treeprint v1.0.0 h1:J0TkWtiuYgtdlrkkrDLISYBQ92M+X5m4LrIIMKrbDTs=
|
||||
github.com/xlab/treeprint v1.0.0/go.mod h1:IoImgRak9i3zJyuxOKUP1v4UZd1tMoKkq/Cimt1uhCg=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9 h1:YTzHMGlqJu67/uEo1lBv0n3wBXhXNeUbB1XfN2vmTm0=
|
||||
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d h1:MiWWjyhUzZ+jvhZvloX6ZrUsdEghn8a64Upd8EMHglE=
|
||||
golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
rsc.io/goversion v1.2.0 h1:SPn+NLTiAG7w30IRK/DKp1BjvpWabYgxlLp/+kx5J8w=
|
||||
rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo=
|
||||
|
Loading…
Reference in New Issue
Block a user