rlimit_unix.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. // Copyright (C) 2015 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. //go:build !windows
  7. // +build !windows
  8. package osutil
  9. import (
  10. "syscall"
  11. "github.com/syncthing/syncthing/lib/build"
  12. )
  13. const (
  14. darwinOpenMax = 10240
  15. )
  16. // MaximizeOpenFileLimit tries to set the resource limit RLIMIT_NOFILE (number
  17. // of open file descriptors) to the max (hard limit), if the current (soft
  18. // limit) is below the max. Returns the new (though possibly unchanged) limit,
  19. // or an error if it could not be changed.
  20. func MaximizeOpenFileLimit() (int, error) {
  21. // Get the current limit on number of open files.
  22. var lim syscall.Rlimit
  23. if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
  24. return 0, err
  25. }
  26. // If we're already at max, there's no need to try to raise the limit.
  27. if lim.Cur >= lim.Max {
  28. return int(lim.Cur), nil
  29. }
  30. // macOS doesn't like a soft limit greater then OPEN_MAX
  31. // See also: man setrlimit
  32. if build.IsDarwin && lim.Max > darwinOpenMax {
  33. lim.Max = darwinOpenMax
  34. }
  35. // Try to increase the limit to the max.
  36. oldLimit := lim.Cur
  37. lim.Cur = lim.Max
  38. if err := syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
  39. return int(oldLimit), err
  40. }
  41. // If the set succeeded, perform a new get to see what happened. We might
  42. // have gotten a value lower than the one in lim.Max, if lim.Max was
  43. // something that indicated "unlimited" (i.e. intmax).
  44. if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil {
  45. // We don't really know the correct value here since Getrlimit
  46. // mysteriously failed after working once... Shouldn't ever happen, I
  47. // think.
  48. return 0, err
  49. }
  50. return int(lim.Cur), nil
  51. }