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 non-nil, is the original soft RLIMIT_NOFILE. 14 var origRlimitNofile atomic.Pointer[Rlimit] 15 16 // Some systems set an artificially low soft limit on open file count, for compatibility 17 // with code that uses select and its hard-coded maximum file descriptor 18 // (limited by the size of fd_set). 19 // 20 // Go does not use select, so it should not be subject to these limits. 21 // On some systems the limit is 256, which is very easy to run into, 22 // even in simple programs like gofmt when they parallelize walking 23 // a file tree. 24 // 25 // After a long discussion on go.dev/issue/46279, we decided the 26 // best approach was for Go to raise the limit unconditionally for itself, 27 // and then leave old software to set the limit back as needed. 28 // Code that really wants Go to leave the limit alone can set the hard limit, 29 // which Go of course has no choice but to respect. 30 func init() { 31 var lim Rlimit 32 if err := Getrlimit(RLIMIT_NOFILE, &lim); err == nil && lim.Cur != lim.Max { 33 origRlimitNofile.Store(&lim) 34 nlim := lim 35 nlim.Cur = nlim.Max 36 adjustFileLimit(&nlim) 37 setrlimit(RLIMIT_NOFILE, &nlim) 38 } 39 } 40 41 func Setrlimit(resource int, rlim *Rlimit) error { 42 if resource == RLIMIT_NOFILE { 43 // Store nil in origRlimitNofile to tell StartProcess 44 // to not adjust the rlimit in the child process. 45 origRlimitNofile.Store(nil) 46 } 47 return setrlimit(resource, rlim) 48 } 49