Skip to content

Commit

Permalink
opt: only enable SO_REUSEPORT on Linux and FreeBSD (panjf2000#580)
Browse files Browse the repository at this point in the history
  • Loading branch information
panjf2000 authored and andyl committed Apr 22, 2024
1 parent e526169 commit 7717171
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 5 deletions.
18 changes: 18 additions & 0 deletions gnet.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"context"
"io"
"net"
"runtime"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -468,6 +469,23 @@ func createListeners(addrs []string, opts ...Option) ([]*listener, *Options, err
options.WriteBufferCap = math.CeilToPowerOfTwo(wbc)
}

// SO_REUSEPORT enables duplicate address and port bindings across various
// Unix-like OSs, whereas there is platform-specific inconsistency:
// Linux implemented SO_REUSEPORT with load balancing for incoming connections
// while *BSD implemented it for only binding to the same address and port, which
// makes it pointless to enable SO_REUSEPORT on *BSD and Darwin for gnet with
// multiple event-loops because only the first event-loop will be constantly woken
// up to accept incoming connections and handle I/O events while the rest of event
// loops remain idle.
// Thus, we disable SO_REUSEPORT on *BSD and Darwin by default.
//
// Note that FreeBSD 12 introduced a new socket option named SO_REUSEPORT_LB
// with the capability of load balancing, it's the equivalent of Linux's SO_REUSEPORT.
goos := runtime.GOOS
if (options.Multicore || options.NumEventLoop > 1) && options.ReusePort && goos != "linux" && goos != "freebsd" {
options.ReusePort = false
}

// If there is UDP listener in the list, enable SO_REUSEPORT and disable edge-triggered I/O by default.
for i := 0; (!options.ReusePort || options.EdgeTriggeredIO) && i < len(addrs); i++ {
proto, _, err := parseProtoAddr(addrs[i])
Expand Down
29 changes: 29 additions & 0 deletions internal/socket/sockopts_freebsd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 (
"os"

"golang.org/x/sys/unix"
)

// SetReuseport enables SO_REUSEPORT_LB option on socket.
func SetReuseport(fd, reusePort int) error {
return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT_LB, reusePort))
}
5 changes: 0 additions & 5 deletions internal/socket/sockopts_posix.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,6 @@ func SetSendBuffer(fd, size int) error {
return unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_SNDBUF, size)
}

// SetReuseport enables SO_REUSEPORT option on socket.
func SetReuseport(fd, reusePort int) error {
return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, reusePort))
}

// SetReuseAddr enables SO_REUSEADDR option on socket.
func SetReuseAddr(fd, reuseAddr int) error {
return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEADDR, reuseAddr))
Expand Down
29 changes: 29 additions & 0 deletions internal/socket/sockopts_unix1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2021 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.

//go:build linux || dragonfly || netbsd || openbsd || darwin
// +build linux dragonfly netbsd openbsd darwin

package socket

import (
"os"

"golang.org/x/sys/unix"
)

// SetReuseport enables SO_REUSEPORT option on socket.
func SetReuseport(fd, reusePort int) error {
return os.NewSyscallError("setsockopt", unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, reusePort))
}

0 comments on commit 7717171

Please sign in to comment.