From dab220bc0b6783b149f8c6ef7e9764128da97f9a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 26 May 2026 11:38:31 -0700 Subject: [PATCH] port rlimit NOFILE Go runtime cache clearing from runc This is the fix for https://github.com/opencontainers/runc/issues/4195. https://github.com/nestybox/sysbox/issues/1014 Signed-off-by: Benjamin Peterson --- libcontainer/init_linux.go | 15 +++++++++++++++ libcontainer/system/rlimit_linux.go | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 libcontainer/system/rlimit_linux.go diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index dc7a3244..fd2de5a6 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -87,6 +87,9 @@ func newContainerInit(t initType, pipe *os.File, consoleSocket, fifoFile *os.Fil if err := json.NewDecoder(pipe).Decode(&config); err != nil { return nil, err } + // Clean the RLIMIT_NOFILE cache in go runtime. + // Issue: https://github.com/opencontainers/runc/issues/4195 + maybeClearRlimitNofileCache(config.Rlimits) if err := populateProcessEnvironment(config.Env); err != nil { return nil, err } @@ -538,6 +541,18 @@ func setupRoute(config *configs.Config) error { return nil } +func maybeClearRlimitNofileCache(limits []configs.Rlimit) { + for _, rlimit := range limits { + if rlimit.Type == syscall.RLIMIT_NOFILE { + system.ClearRlimitNofileCache(&syscall.Rlimit{ + Cur: rlimit.Soft, + Max: rlimit.Hard, + }) + return + } + } +} + func setupRlimits(limits []configs.Rlimit, pid int) error { for _, rlimit := range limits { if err := system.Prlimit(pid, rlimit.Type, unix.Rlimit{Max: rlimit.Hard, Cur: rlimit.Soft}); err != nil { diff --git a/libcontainer/system/rlimit_linux.go b/libcontainer/system/rlimit_linux.go new file mode 100644 index 00000000..8add993c --- /dev/null +++ b/libcontainer/system/rlimit_linux.go @@ -0,0 +1,13 @@ +package system + +import ( + "syscall" +) + +// ClearRlimitNofileCache clears go runtime's nofile rlimit cache. The argument +// is process RLIMIT_NOFILE values. Relies on go.dev/cl/588076. +func ClearRlimitNofileCache(lim *syscall.Rlimit) { + // Ignore the return values since we only need to clean the cache, + // the limit is going to be set via unix.Prlimit elsewhere. + _ = syscall.Setrlimit(syscall.RLIMIT_NOFILE, lim) +}