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 7package syscall 8 9import ( 10 "sync/atomic" 11) 12 13// origRlimitNofile, if non-nil, is the original soft RLIMIT_NOFILE. 14var 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. 30func 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 41func 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