Source file src/syscall/rlimit.go
1 // Copyright 2022 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build unix 6 7 package syscall 8 9 import ( 10 "sync/atomic" 11 ) 12 13 // origRlimitNofile, if not {0, 0}, is the original soft RLIMIT_NOFILE. 14 // When we can assume that we are bootstrapping with Go 1.19, 15 // this can be atomic.Pointer[Rlimit]. 16 var origRlimitNofile atomic.Value // of Rlimit 17 18 // Some systems set an artificially low soft limit on open file count, for compatibility 19 // with code that uses select and its hard-coded maximum file descriptor 20 // (limited by the size of fd_set). 21 // 22 // Go does not use select, so it should not be subject to these limits. 23 // On some systems the limit is 256, which is very easy to run into, 24 // even in simple programs like gofmt when they parallelize walking 25 // a file tree. 26 // 27 // After a long discussion on go.dev/issue/46279, we decided the 28 // best approach was for Go to raise the limit unconditionally for itself, 29 // and then leave old software to set the limit back as needed. 30 // Code that really wants Go to leave the limit alone can set the hard limit, 31 // which Go of course has no choice but to respect. 32 func init() { 33 var lim Rlimit 34 if err := Getrlimit(RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max { 35 origRlimitNofile.Store(lim) 36 lim.Cur = lim.Max 37 adjustFileLimit(&lim) 38 setrlimit(RLIMIT_NOFILE, &lim) 39 } 40 } 41 42 func Setrlimit(resource int, rlim *Rlimit) error { 43 err := setrlimit(resource, rlim) 44 if err == nil && resource == RLIMIT_NOFILE { 45 // Store zeroes in origRlimitNofile to tell StartProcess 46 // to not adjust the rlimit in the child process. 47 origRlimitNofile.Store(Rlimit{0, 0}) 48 } 49 return err 50 } 51