Summary
process_rlimits.t sets RLIMIT_NOFILE soft=3000, hard=4000 in the OCI config, but the test always fails because the Go runtime's syscall.init() silently raises the soft limit to hard - 1 (3999) before any test code runs.
Reproduction
Run validation/process_rlimits/process_rlimits.t against any runtime on a system with Go 1.19+. The assertion:
not ok 13 - has expected soft RLIMIT_NOFILE
actual: 3999, expected: 3000
The hard limit check passes (4000 == 4000). Only the soft limit fails.
Root cause
Go 1.19 added an init() in src/syscall/rlimit.go (golang/go#46279) that runs unconditionally at process startup on Linux:
func init() {
var lim Rlimit
if err := Getrlimit(RLIMIT_NOFILE, &lim); err == nil && lim.Max > 0 && lim.Cur < lim.Max-1 {
origRlimitNofile.Store(&lim)
nlim := lim
nlim.Cur = nlim.Max - 1 // raises soft to hard - 1
setrlimit(RLIMIT_NOFILE, &nlim)
}
}
This runs in runtimetest before main(). The runtime correctly sets soft=3000, hard=4000 via setrlimit. Then Go's init raises soft to 3999. The test then reads 3999 and compares it to the expected 3000.
Impact
This test is permanently broken against any runtimetest binary compiled with Go 1.19 or later. It cannot pass regardless of runtime correctness.
Fix options
- Exclude
RLIMIT_NOFILE from the process_rlimits test with a comment explaining the Go init conflict.
- Change the test to check
rlimit.Cur >= r.Soft (accept Go's upward-only raise as valid).
- Use a different resource (e.g.
RLIMIT_CORE) that Go does not auto-adjust.
- Set soft == hard in the config so Go's raise is a no-op (though this weakens the test).
Summary
process_rlimits.tsetsRLIMIT_NOFILEsoft=3000, hard=4000 in the OCI config, but the test always fails because the Go runtime'ssyscall.init()silently raises the soft limit tohard - 1(3999) before any test code runs.Reproduction
Run
validation/process_rlimits/process_rlimits.tagainst any runtime on a system with Go 1.19+. The assertion:The hard limit check passes (4000 == 4000). Only the soft limit fails.
Root cause
Go 1.19 added an
init()insrc/syscall/rlimit.go(golang/go#46279) that runs unconditionally at process startup on Linux:This runs in
runtimetestbeforemain(). The runtime correctly sets soft=3000, hard=4000 viasetrlimit. Then Go's init raises soft to 3999. The test then reads 3999 and compares it to the expected 3000.Impact
This test is permanently broken against any
runtimetestbinary compiled with Go 1.19 or later. It cannot pass regardless of runtime correctness.Fix options
RLIMIT_NOFILEfrom theprocess_rlimitstest with a comment explaining the Go init conflict.rlimit.Cur >= r.Soft(accept Go's upward-only raise as valid).RLIMIT_CORE) that Go does not auto-adjust.