Browse Source

Merge pull request #2160 from calmh/rlimit

Increase open file (fd) limit if possible
Audrius Butkevicius 10 years ago
parent
commit
f3f586773b
3 changed files with 69 additions and 0 deletions
  1. 5 0
      cmd/syncthing/main.go
  2. 47 0
      lib/osutil/rlimit_unix.go
  3. 17 0
      lib/osutil/rlimit_windows.go

+ 5 - 0
cmd/syncthing/main.go

@@ -454,6 +454,11 @@ func syncthingMain() {
 		runtime.GOMAXPROCS(runtime.NumCPU())
 	}
 
+	// Attempt to increase the limit on number of open files to the maximum
+	// allowed, in case we have many peers. We don't really care enough to
+	// report the error if there is one.
+	osutil.MaximizeOpenFileLimit()
+
 	// Ensure that that we have a certificate and key.
 	cert, err := tls.LoadX509KeyPair(locations[locCertFile], locations[locKeyFile])
 	if err != nil {

+ 47 - 0
lib/osutil/rlimit_unix.go

@@ -0,0 +1,47 @@
+// Copyright (C) 2015 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// +build !windows
+
+package osutil
+
+import "syscall"
+
+// MaximizeOpenFileLimit tries to set the resoure limit RLIMIT_NOFILE (number
+// of open file descriptors) to the max (hard limit), if the current (soft
+// limit) is below the max. Returns the new (though possibly unchanged) limit,
+// or an error if it was could not be changed.
+func MaximizeOpenFileLimit() (int, error) {
+	// Get the current limit on number of open files.
+	var lim syscall.Rlimit
+	if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
+		return 0, err
+	}
+
+	// If we're already at max, there's no need to try to raise the limit.
+	if lim.Cur >= lim.Max {
+		return int(lim.Cur), nil
+	}
+
+	// Try to increase the limit to the max.
+	oldLimit := lim.Cur
+	lim.Cur = lim.Max
+	if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
+		return int(oldLimit), err
+	}
+
+	// If the set succeeded, perform a new get to see what happened. We might
+	// have gotten a value lower than the one in lim.Max, if lim.Max was
+	// something that indiciated "unlimited" (i.e. intmax).
+	if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
+		// We don't really know the correct value here since Getrlimit
+		// mysteriously failed after working once... Shouldn't ever happen, I
+		// think.
+		return 0, err
+	}
+
+	return int(lim.Cur), nil
+}

+ 17 - 0
lib/osutil/rlimit_windows.go

@@ -0,0 +1,17 @@
+// Copyright (C) 2015 The Syncthing Authors.
+//
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at http://mozilla.org/MPL/2.0/.
+
+// +build windows
+
+package osutil
+
+import (
+	"errors"
+)
+
+func MaximizeOpenFileLimit() (int, error) {
+	return 0, errors.New("not relevant on Windows")
+}