aboutsummaryrefslogtreecommitdiff
path: root/src/syscall/rlimit.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/syscall/rlimit.go')
-rw-r--r--src/syscall/rlimit.go50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/syscall/rlimit.go b/src/syscall/rlimit.go
new file mode 100644
index 0000000000..06e7a5d8b1
--- /dev/null
+++ b/src/syscall/rlimit.go
@@ -0,0 +1,50 @@
+// Copyright 2022 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
+
+package syscall
+
+import (
+ "sync/atomic"
+)
+
+// origRlimitNofile, if not {0, 0}, is the original soft RLIMIT_NOFILE.
+// When we can assume that we are bootstrapping with Go 1.19,
+// this can be atomic.Pointer[Rlimit].
+var origRlimitNofile atomic.Value // of Rlimit
+
+// Some systems set an artificially low soft limit on open file count, for compatibility
+// with code that uses select and its hard-coded maximum file descriptor
+// (limited by the size of fd_set).
+//
+// Go does not use select, so it should not be subject to these limits.
+// On some systems the limit is 256, which is very easy to run into,
+// even in simple programs like gofmt when they parallelize walking
+// a file tree.
+//
+// After a long discussion on go.dev/issue/46279, we decided the
+// best approach was for Go to raise the limit unconditionally for itself,
+// and then leave old software to set the limit back as needed.
+// Code that really wants Go to leave the limit alone can set the hard limit,
+// which Go of course has no choice but to respect.
+func init() {
+ var lim Rlimit
+ if err := Getrlimit(RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max {
+ origRlimitNofile.Store(lim)
+ lim.Cur = lim.Max
+ adjustFileLimit(&lim)
+ setrlimit(RLIMIT_NOFILE, &lim)
+ }
+}
+
+func Setrlimit(resource int, rlim *Rlimit) error {
+ err := setrlimit(resource, rlim)
+ if err == nil && resource == RLIMIT_NOFILE {
+ // Store zeroes in origRlimitNofile to tell StartProcess
+ // to not adjust the rlimit in the child process.
+ origRlimitNofile.Store(Rlimit{0, 0})
+ }
+ return err
+}