|
|
@@ -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
|
|
|
+}
|