From 5c9d4ecd511bf992e2ea7ba3374abf961b85eacb Mon Sep 17 00:00:00 2001 From: John Cai Date: Thu, 14 May 2020 13:27:22 -0700 Subject: Allow socket reuse in tableflip --- internal/bootstrap/bootstrap.go | 17 ++++++++++++++++- internal/bootstrap/bootstrap_test.go | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'internal/bootstrap') diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go index 214487e63..839906003 100644 --- a/internal/bootstrap/bootstrap.go +++ b/internal/bootstrap/bootstrap.go @@ -11,6 +11,7 @@ import ( "github.com/cloudflare/tableflip" log "github.com/sirupsen/logrus" "gitlab.com/gitlab-org/gitaly/internal/config" + "golang.org/x/sys/unix" ) const ( @@ -67,7 +68,21 @@ func New() (*Bootstrap, error) { _, upgradesEnabled := os.LookupEnv(EnvUpgradesEnabled) // PIDFile is optional, if provided tableflip will keep it updated - upg, err := tableflip.New(tableflip.Options{PIDFile: pidFile}) + upg, err := tableflip.New(tableflip.Options{ + PIDFile: pidFile, + ListenConfig: &net.ListenConfig{ + Control: func(network, address string, c syscall.RawConn) error { + var opErr error + err := c.Control(func(fd uintptr) { + opErr = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEPORT, 1) + }) + if err != nil { + return err + } + return opErr + }, + }, + }) if err != nil { return nil, err } diff --git a/internal/bootstrap/bootstrap_test.go b/internal/bootstrap/bootstrap_test.go index 15c43fba5..16e85fe65 100644 --- a/internal/bootstrap/bootstrap_test.go +++ b/internal/bootstrap/bootstrap_test.go @@ -201,6 +201,24 @@ func TestGracefulTermination(t *testing.T) { require.Contains(t, err.Error(), "completed") } +func TestPortReuse(t *testing.T) { + var addr string + + b, err := New() + require.NoError(t, err) + + l, err := b.listen("tcp", "0.0.0.0:") + require.NoError(t, err, "failed to bind") + + addr = l.Addr().String() + _, port, err := net.SplitHostPort(addr) + require.NoError(t, err) + + l, err = b.listen("tcp", "0.0.0.0:"+port) + require.NoError(t, err, "failed to bind") + require.NoError(t, l.Close()) +} + func testGracefulUpdate(t *testing.T, server *testServer, b *Bootstrap, waitTimeout time.Duration, duringGracePeriodCallback func()) error { defer func(oldVal time.Duration) { config.Config.GracefulRestartTimeout = oldVal -- cgit v1.2.3