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.Max > 0 && lim.Cur < lim.Max-1 { 33 origRlimitNofile.Store(&lim) 34 nlim := lim 35 36 // We set Cur to Max - 1 so that we are more likely to 37 // detect cases where another process uses prlimit 38 // to change our resource limits. The theory is that 39 // using prlimit to change to Cur == Max is more likely 40 // than using prlimit to change to Cur == Max - 1. 41 // The place we check for this is in exec_linux.go. 42 nlim.Cur = nlim.Max - 1 43 44 adjustFileLimit(&nlim) 45 setrlimit(RLIMIT_NOFILE, &nlim) 46 } 47 } 48 49 func Setrlimit(resource int, rlim *Rlimit) error { 50 if resource == RLIMIT_NOFILE { 51 // Store nil in origRlimitNofile to tell StartProcess 52 // to not adjust the rlimit in the child process. 53 origRlimitNofile.Store(nil) 54 } 55 return setrlimit(resource, rlim) 56 } 57