From e6b19ae19cb1a1f2f5d74b811387162c49b7af1b Mon Sep 17 00:00:00 2001 From: dgupta52 Date: Wed, 8 Oct 2025 12:38:46 -0500 Subject: [PATCH 1/3] refactor(sandbox): move resource fields into SandboxMeta.Limits and resolve defaults in pools --- go/worker/sandbox/api.go | 10 +++++----- go/worker/sandbox/dockerPool.go | 11 +++++++---- go/worker/sandbox/sandbox.go | 17 ++--------------- go/worker/sandbox/sock.go | 2 +- go/worker/sandbox/sockPool.go | 9 ++++++--- 5 files changed, 21 insertions(+), 28 deletions(-) diff --git a/go/worker/sandbox/api.go b/go/worker/sandbox/api.go index bbe215cf3..0e23dbc67 100644 --- a/go/worker/sandbox/api.go +++ b/go/worker/sandbox/api.go @@ -1,8 +1,9 @@ package sandbox import ( - "github.com/open-lambda/open-lambda/go/common" "net/http" + + "github.com/open-lambda/open-lambda/go/common" ) type SandboxPool interface { @@ -85,10 +86,9 @@ type Sandbox interface { } type SandboxMeta struct { - Installs []string - Imports []string - MemLimitMB int - CPUPercent int + Installs []string + Imports []string + Limits common.Limits // required; zeros = use defaults } type SandboxError string diff --git a/go/worker/sandbox/dockerPool.go b/go/worker/sandbox/dockerPool.go index eed42599c..14401ac2f 100644 --- a/go/worker/sandbox/dockerPool.go +++ b/go/worker/sandbox/dockerPool.go @@ -61,7 +61,11 @@ func NewDockerPool(pidMode string, caps []string) (*DockerPool, error) { // Create creates a docker sandbox from the handler and sandbox directory. func (pool *DockerPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir string, meta *SandboxMeta, _ common.RuntimeType) (sb Sandbox, err error) { - meta = fillMetaDefaults(meta) + if meta == nil { + meta = &SandboxMeta{} + } + // Resolve zero-valued limits to worker defaults + meta.Limits.FillDefaults(common.Conf.Limits.ToLimits()) t := common.T0("Create()") defer t.T1() @@ -108,7 +112,6 @@ func (pool *DockerPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir // create the container using the specified configuration procLimit := int64(common.Conf.Limits.Procs) swappiness := int64(common.Conf.Limits.Swappiness) - cpuPercent := int64(common.Conf.Limits.CPU_percent) container, err := pool.client.CreateContainer( docker.CreateContainerOptions{ Config: &docker.Config{ @@ -124,8 +127,8 @@ func (pool *DockerPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir Runtime: pool.dockerRuntime, PidsLimit: &procLimit, MemorySwappiness: &swappiness, - CPUPercent: cpuPercent, - Memory: int64(meta.MemLimitMB * 1024 * 1024), + CPUPercent: int64(meta.Limits.CPUPercent), + Memory: int64(meta.Limits.MemMB * 1024 * 1024), }, }, ) diff --git a/go/worker/sandbox/sandbox.go b/go/worker/sandbox/sandbox.go index a6a525bf4..9bf9255e7 100644 --- a/go/worker/sandbox/sandbox.go +++ b/go/worker/sandbox/sandbox.go @@ -23,22 +23,9 @@ func SandboxPoolFromConfig(name string, sizeMb int) (cf SandboxPool, err error) return nil, fmt.Errorf("invalid sandbox type: '%s'", common.Conf.Sandbox) } -func fillMetaDefaults(meta *SandboxMeta) *SandboxMeta { - if meta == nil { - meta = &SandboxMeta{} - } - if meta.MemLimitMB == 0 { - meta.MemLimitMB = common.Conf.Limits.Mem_mb - } - if meta.CPUPercent == 0 { - meta.CPUPercent = common.Conf.Limits.CPU_percent - } - return meta -} - func (meta *SandboxMeta) String() string { - return fmt.Sprintf("", - strings.Join(meta.Installs, ","), strings.Join(meta.Imports, ","), meta.MemLimitMB) + return fmt.Sprintf("", + strings.Join(meta.Installs, ","), strings.Join(meta.Imports, ","), meta.Limits.MemMB) } func (e SandboxError) Error() string { diff --git a/go/worker/sandbox/sock.go b/go/worker/sandbox/sock.go index 9ee3c9491..782dbff60 100644 --- a/go/worker/sandbox/sock.go +++ b/go/worker/sandbox/sock.go @@ -259,7 +259,7 @@ func (container *SOCKContainer) Unpause() (err error) { // block until we have enough mem to upsize limit to the // normal size before unpausing oldLimit := container.cg.GetMemLimitMB() - newLimit := common.Conf.Limits.Mem_mb + newLimit := container.meta.Limits.MemMB container.pool.mem.adjustAvailableMB(oldLimit - newLimit) container.cg.SetMemLimitMB(newLimit) } diff --git a/go/worker/sandbox/sockPool.go b/go/worker/sandbox/sockPool.go index ab0c6ff57..3200c15a2 100644 --- a/go/worker/sandbox/sockPool.go +++ b/go/worker/sandbox/sockPool.go @@ -65,8 +65,11 @@ func sbStr(sb Sandbox) string { } func (pool *SOCKPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir string, meta *SandboxMeta, rtType common.RuntimeType) (sb Sandbox, err error) { + if meta == nil { + meta = &SandboxMeta{} + } + meta.Limits.FillDefaults(common.Conf.Limits.ToLimits()) id := fmt.Sprintf("%d", atomic.AddInt64(&nextId, 1)) - meta = fillMetaDefaults(meta) pool.printf("<%v>.Create(%v, %v, %v, %v, %v)=%s...", pool.name, sbStr(parent), isLeaf, codeDir, scratchDir, meta, id) defer func() { pool.printf("...returns %v, %v", sbStr(sb), err) @@ -91,7 +94,7 @@ func (pool *SOCKPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir st // block until we have enough to cover the cgroup mem limits t2 := t.T0("acquire-mem") - pool.mem.adjustAvailableMB(-meta.MemLimitMB) + pool.mem.adjustAvailableMB(-meta.Limits.MemMB) t2.T1() t2 = t.T0("acquire-cgroup") @@ -101,7 +104,7 @@ func (pool *SOCKPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir st // don't want to use this cgroup feature, because the child // would take the blame for ALL of the parent's allocations moveMemCharge := (parent == nil) - cSock.cg = pool.cgPool.GetCg(meta.MemLimitMB, moveMemCharge, meta.CPUPercent) + cSock.cg = pool.cgPool.GetCg(meta.Limits.MemMB, moveMemCharge, meta.Limits.CPUPercent) t2.T1() cSock.printf("use cgroup %s", cSock.cg.Name()) From 4a8fd7e95670df6c0b8574deb623e85ef17002c1 Mon Sep 17 00:00:00 2001 From: dgupta52 Date: Wed, 8 Oct 2025 12:53:49 -0500 Subject: [PATCH 2/3] fix(packages): adapt SandboxMeta construction to new Limits field --- go/worker/lambda/packages/packagePuller.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/go/worker/lambda/packages/packagePuller.go b/go/worker/lambda/packages/packagePuller.go index 299329ca0..ba0a51deb 100644 --- a/go/worker/lambda/packages/packagePuller.go +++ b/go/worker/lambda/packages/packagePuller.go @@ -177,7 +177,10 @@ func (pp *PackagePuller) sandboxInstall(p *Package) (err error) { }() meta := &sandbox.SandboxMeta{ - MemLimitMB: common.Conf.Limits.Installer_mem_mb, + Limits: common.Limits{ + MemMB: common.Conf.Limits.Installer_mem_mb, + // CPUPercent and RuntimeSec left as zero to use defaults + }, } sb, err := pp.sbPool.Create(nil, true, pp.pipLambda, scratchDir, meta, common.RT_PYTHON) if err != nil { From e0fe3857e0cfac1bcdf6eca0f6945634a5b6e73e Mon Sep 17 00:00:00 2001 From: dgupta52 Date: Wed, 8 Oct 2025 13:27:47 -0500 Subject: [PATCH 3/3] fix(sandbox): use resolved per-sandbox RuntimeSec for HTTP client timeout --- go/worker/sandbox/dockerPool.go | 3 +-- go/worker/sandbox/sockPool.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/go/worker/sandbox/dockerPool.go b/go/worker/sandbox/dockerPool.go index 14401ac2f..d990783b9 100644 --- a/go/worker/sandbox/dockerPool.go +++ b/go/worker/sandbox/dockerPool.go @@ -172,9 +172,8 @@ func (pool *DockerPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir c.httpClient = &http.Client{ Transport: &http.Transport{Dial: dial}, - Timeout: time.Second * time.Duration(common.Conf.Limits.Max_runtime_default), + Timeout: time.Second * time.Duration(meta.Limits.RuntimeSec), } - // wrap to make thread-safe and handle container death safe := newSafeSandbox(c) safe.startNotifyingListeners(pool.eventHandlers) diff --git a/go/worker/sandbox/sockPool.go b/go/worker/sandbox/sockPool.go index 3200c15a2..2709bf0dd 100644 --- a/go/worker/sandbox/sockPool.go +++ b/go/worker/sandbox/sockPool.go @@ -195,7 +195,7 @@ func (pool *SOCKPool) Create(parent Sandbox, isLeaf bool, codeDir, scratchDir st cSock.client = &http.Client{ Transport: &http.Transport{Dial: dial}, - Timeout: time.Second * time.Duration(common.Conf.Limits.Max_runtime_default), + Timeout: time.Second * time.Duration(meta.Limits.RuntimeSec), } // event handling