Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add util to raise file descriptor limits #346

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions main/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/ava-labs/gecko/staking"
"github.com/ava-labs/gecko/utils"
"github.com/ava-labs/gecko/utils/constants"
"github.com/ava-labs/gecko/utils/fdlimit"
"github.com/ava-labs/gecko/utils/hashing"
"github.com/ava-labs/gecko/utils/logging"
"github.com/ava-labs/gecko/utils/sampler"
Expand Down Expand Up @@ -239,6 +240,10 @@ func init() {
ipcsChainIDs := fs.String("ipcs-chain-ids", "", "Comma separated list of chain ids to add to the IPC engine. Example: 11111111111111111111111111111111LpoYY,4R5p2RXDGLqaifZE4hHWH9owe34pfoBULn1DrQTWivjg8o4aH")
fs.StringVar(&Config.IPCPath, "ipcs-path", ipcs.DefaultBaseURL, "The directory (Unix) or named pipe name prefix (Windows) for IPC sockets")

// File Descriptors
var fdLimit uint64
fs.Uint64Var(&fdLimit, "fd-limit", fdlimit.DefaultFdLimit, "Attempts to raise the process file descriptor limit to at least this value.")

ferr := fs.Parse(os.Args[1:])

if *version { // If --version used, print version and exit
Expand Down Expand Up @@ -444,4 +449,10 @@ func init() {
if *ipcsChainIDs != "" {
Config.IPCDefaultChainIDs = strings.Split(*ipcsChainIDs, ",")
}

// File Descriptors
if err := fdlimit.RaiseLimit(fdLimit); err != nil {
errs.Add(err)
return
}
}
61 changes: 61 additions & 0 deletions utils/fdlimit/fdlimit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// +build !windows

package fdlimit

import (
"fmt"
"syscall"
)

const (
// DefaultFdLimit is the default value to raise the file
// descriptor limit to on startup.
DefaultFdLimit uint64 = 4096
)

// Based off of Quorum implementation:
// https://github.com/ConsenSys/quorum/tree/c215989c10f191924e6b5b668ba4ed8ed425ded1/common/fdlimit

// GetLimit returns the current and max file descriptor limit
func GetLimit() (uint64, uint64, error) {
var limit syscall.Rlimit
err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit)
return limit.Cur, limit.Max, err
}

// RaiseLimit attempts to raise the file descriptor limit to at least [fdLimit]
func RaiseLimit(fdLimit uint64) error {
// Get the current and maximum file descriptor limit
var limit syscall.Rlimit
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return err
}

// Check if it is necessary or possible to raise the file descriptor limit
if limit.Cur >= fdLimit {
return nil
}
if limit.Max < fdLimit {
return fmt.Errorf("Cannot raise fd limit to %d because it is above system maximum of %d", fdLimit, limit.Max)
}

// Attempt to increase the file descriptor limit to [fdLimit]
limit.Cur = fdLimit
if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return err
}

// Get the limit one last time to ensure that the OS made
// the requested change
if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &limit); err != nil {
return err
}
if limit.Cur < fdLimit {
return fmt.Errorf("Raising the fd limit failed to take effect")
}

return nil
}
28 changes: 28 additions & 0 deletions utils/fdlimit/fdlimit_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package fdlimit

import "testing"

// Based off of Quorum implementation:
// https://github.com/ConsenSys/quorum/tree/c215989c10f191924e6b5b668ba4ed8ed425ded1/common/fdlimit

func TestFileDescriptorLimits(t *testing.T) {
_, _, err := GetLimit()
if err != nil {
t.Fatalf("Failed to get file descriptor limits: %s", err)
}

if err := RaiseLimit(DefaultFdLimit); err != nil {
t.Fatalf("Failed to raise file descriptor limit: %s", err)
}

cur, _, err := GetLimit()
if err != nil {
t.Fatalf("Failed to get file descriptor limits after attempting to raise the limit: %s", err)
}
if cur < DefaultFdLimit {
t.Fatalf("Failed to raise the file descriptor limit. Target: %d. Current Value: %d.", DefaultFdLimit, cur)
}
}
37 changes: 37 additions & 0 deletions utils/fdlimit/fdlimit_windows.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// (c) 2019-2020, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

// This tag is applied for consistency with fdlimit.go, but
// is redundant because this file also uses *_windows.go suffix
// +build windows

package fdlimit

import (
"fmt"
)

const (
// DefaultFdLimit is the default value to raise the file
// descriptor limit to on startup.
DefaultFdLimit uint64 = 4096
// Cannot adjust the fd limit set by the Windows OS
// so these operations are NOPs
windowsHardLimit uint64 = 16384
)

// Based off of Quorum implementation:
// https://github.com/ConsenSys/quorum/tree/c215989c10f191924e6b5b668ba4ed8ed425ded1/common/fdlimit

// GetLimit returns the current and max file descriptor limit
func GetLimit() (uint64, uint64, error) {
return windowsHardLimit, windowsHardLimit, nil
}

// RaiseLimit attempts to raise the file descriptor limit to at least [fdLimit]
func RaiseLimit(fdLimit uint64) error {
if fdLimit > windowsHardLimit {
return fmt.Errorf("Cannot raise the file descriptor limit above %d to %d on Windows OS", windowsHardLimit, fdLimit)
}
return nil
}