From c4d8ae3f90b31266ca6416f167592c2e39acddd0 Mon Sep 17 00:00:00 2001 From: Kenneth Jenkins <51246568+kenjenkins@users.noreply.github.com> Date: Fri, 3 May 2024 10:42:14 -0700 Subject: [PATCH] envoy: preserve Go's max file limit for Envoy Go raises the "max open files" soft limit to match the hard limit for itself, but has special logic to reset the original soft limit before forking a child process. This logic does not apply if the file limit is set explicitly. Add a pair of Getrlimit / Setrlimit calls so that we (1) preserve the default Go limit behavior for ourselves, and (2) keep these same limits when launching Envoy. --- pkg/envoy/envoy.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/pkg/envoy/envoy.go b/pkg/envoy/envoy.go index 40951d8fa..62f2d34c9 100644 --- a/pkg/envoy/envoy.go +++ b/pkg/envoy/envoy.go @@ -16,6 +16,7 @@ import ( "strconv" "strings" "sync" + "syscall" "time" "github.com/cenkalti/backoff/v4" @@ -57,6 +58,10 @@ type Server struct { // NewServer creates a new server with traffic routed by envoy. func NewServer(ctx context.Context, src config.Source, builder *envoyconfig.Builder) (*Server, error) { + if err := preserveRlimitNofile(); err != nil { + log.Debug(ctx).Err(err).Msg("couldn't preserve RLIMIT_NOFILE before starting Envoy") + } + envoyPath, err := Extract() if err != nil { return nil, fmt.Errorf("extracting envoy: %w", err) @@ -300,3 +305,17 @@ func (srv *Server) monitorProcess(ctx context.Context, pid int32) { } } } + +func preserveRlimitNofile() error { + // Go raises the "max open files" soft limit to match the hard limit for + // itself, but has special logic to reset the original soft limit before + // forking a child process. This logic does not apply if the file limit is + // set explicitly. This pair of Getrlimit / Setrlimit calls is intended to + // (1) preserve the default Go limit behavior for ourselves, and + // (2) keep these same limits when launching Envoy. + var lim syscall.Rlimit + if err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &lim); err != nil { + return err + } + return syscall.Setrlimit(syscall.RLIMIT_NOFILE, &lim) +}