Summary
The AWF agent sandbox enforces a process/thread ceiling that is invisible from inside the container: /sys/fs/cgroup exposes no files, ulimit -u reports unlimited, and no sandbox.agent: option configures it. JVM-based build tools (javac, the Android manifest merger) size their thread pools from visible cores, hit the ceiling only when two build lanes run concurrently, and die with thread-creation failures that look like code bugs. There is currently no way to measure the limit, raise it, or let tools self-limit.
Environment
- gh-aw v0.86.1, AWF v0.27.43 (rootless), engine: copilot
- Runner: WarpBuild
warp-ubuntu-latest-x64-16x (16 cores / 64 GB)
sandbox.agent.memory: 56g — memory is not the trigger; the measured co-resident peak of the workload is ~44 GB host-wide, and the failures below are thread/process creation, not OOM
- Workload: building a large multi-platform .NET repository; the Android leg (
dotnet build of a Xamarin/.NET-Android solution) spawns javac and manifest-merger JVMs
What happens
Running the Android build concurrently with one other platform build inside the agent container fails three different ways across three runs (repository is private — Devolutions/RDM — run IDs included for reference):
- javac:
JAVAC0000: unable to create native thread: possibly out of memory or process/resource limits reached (run 31243184658)
- manifest merger:
XAAMM0000 Cannot create worker GC thread (run 31243925337)
- Total starvation: the non-Android legs died within 11–15 s of starting and the Android build alone crawled until a 25-minute timeout (run 31245907722)
The identical concurrent flow on the same runner outside the sandbox works and is our motivation for wanting it inside: all six platforms build in 9m04s overlapped vs 14m43s serial (run 31242423191).
What we probed from inside the container
/sys/fs/cgroup contains no readable files — no pids.max, pids.current, memory.max, so tools cannot discover the budget and self-limit
ulimit -u reports unlimited for both soft and hard limits (raising soft to hard changes nothing)
-XX:ActiveProcessorCount=8 on the JVMs and lowering MSBuild -maxcpucount do not prevent the failures
- Neither gh-aw frontmatter nor AWF exposes a pids/process knob
Ask
Either (or ideally both) of:
- A configurable pids/process limit under
sandbox.agent:, alongside the existing memory: — so workloads that need concurrency can pay for it explicitly.
- Cgroup visibility inside the agent container (e.g. mount the delegated cgroup subtree read-only) — JVMs and build orchestrators read
pids.max and size their thread pools accordingly, and our own tooling could then auto-serialize when the budget is too small.
Even documenting the effective ceiling would help: today the limit can only be discovered by crashing into it, and the crash signatures (JAVAC0000, XAAMM0000, GC worker thread failures) point at the build rather than at the sandbox.
Summary
The AWF agent sandbox enforces a process/thread ceiling that is invisible from inside the container:
/sys/fs/cgroupexposes no files,ulimit -ureports unlimited, and nosandbox.agent:option configures it. JVM-based build tools (javac, the Android manifest merger) size their thread pools from visible cores, hit the ceiling only when two build lanes run concurrently, and die with thread-creation failures that look like code bugs. There is currently no way to measure the limit, raise it, or let tools self-limit.Environment
warp-ubuntu-latest-x64-16x(16 cores / 64 GB)sandbox.agent.memory: 56g— memory is not the trigger; the measured co-resident peak of the workload is ~44 GB host-wide, and the failures below are thread/process creation, not OOMdotnet buildof a Xamarin/.NET-Android solution) spawns javac and manifest-merger JVMsWhat happens
Running the Android build concurrently with one other platform build inside the agent container fails three different ways across three runs (repository is private — Devolutions/RDM — run IDs included for reference):
JAVAC0000: unable to create native thread: possibly out of memory or process/resource limits reached(run 31243184658)XAAMM0000 Cannot create worker GC thread(run 31243925337)The identical concurrent flow on the same runner outside the sandbox works and is our motivation for wanting it inside: all six platforms build in 9m04s overlapped vs 14m43s serial (run 31242423191).
What we probed from inside the container
/sys/fs/cgroupcontains no readable files — nopids.max,pids.current,memory.max, so tools cannot discover the budget and self-limitulimit -ureportsunlimitedfor both soft and hard limits (raising soft to hard changes nothing)-XX:ActiveProcessorCount=8on the JVMs and lowering MSBuild-maxcpucountdo not prevent the failuresAsk
Either (or ideally both) of:
sandbox.agent:, alongside the existingmemory:— so workloads that need concurrency can pay for it explicitly.pids.maxand size their thread pools accordingly, and our own tooling could then auto-serialize when the budget is too small.Even documenting the effective ceiling would help: today the limit can only be discovered by crashing into it, and the crash signatures (
JAVAC0000,XAAMM0000, GC worker thread failures) point at the build rather than at the sandbox.