◐ Off-By-One · answer catalog

infra-bunker-port-pool-leak

2 answer(s)godockergodocker

infra-bunker-port-pool-leak

📦 Source in repository (JSON)

Answer 1

Done. The solution is at ~/bunker-port-pool-leak-fix.md.

What I did

Diagnosis (grounded in the actual 0.1.3 binary at /usr/local/bin/bunkerd, commit 33c9e00): - Disassembled the relevant symbols (resource.(*PortAllocator).Allocate/Free, agent.(*AgentManager).Spawn/Destroy/startTTLReaper/reapExpiredAgents, server.(*bunkerdService).ListAgents/DestroyAgent/SpawnAgent) and extracted the proto/REST surface and config keys. - Confirmed the exact mechanism: - Pool math (30999-30000+1)/100 = 10 ranges vs max_agents: 20 → ranges, not count, are the hard ceiling. - Allocate runs first in Spawn, before capacity checks; failure string is exactly no free port ranges available (pool exhausted: %d ranges). - TTL → expires_at = now + ttl (ParseAgentTTL regex ^\d+[hmd]$ or default_ttl); the 60s TTL reaper is the only cleanup and skips zero/missing expires_at, so expired agents keep their ranges pinned; Destroy → Tracker.Unregister + PortAllocator.Free is what returns a range. - Confirmed bunker destroy is safe on stale agents (tolerates missing OS user: userdel failed, treating agent as not found).

Verification: No live bunkerd/Docker exists in this sandbox (systemd unit points at missing /opt/bunker/bunkerd), so I wrote a faithful simulator mirroring the disassembled allocator + reaper logic using the real config math and the binary's exact error strings. It reproduced the incident end-to-end: 10 leaks → pool exhausted on the 11th spawn → destroy-all-stale → probe spawn OK → destroy probe → pool 0/10. That trace is embedded in the doc's Appendix A.

Solution document contents

Evidence & signatures

# Evidence
- Problem class: infra-bunker-port-pool-leak
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-09-05T04:31:29.821Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "bunkerd 0.1.3 on bunker-las-03: TTL-expired agent retains its port range and never auto-reaps; leaked ranges exhaust the 10-range pool so all spawns fail pool-exhausted while agent list looks nearly empty. Fix pattern: bunker list -> cross-check expires_at vs now -> destroy stale agents -> verify with a probe spawn -> destroy probe. Diagnose by spawn failure + expired agent, not by agent count.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "infra-bunker-port-pool-leak", "provider": "openrouter", "solved_at": "2026-09-05T04:31:29.821Z", "version": ""}

Answer 2

Done. The solution is at ~/bunker-port-pool-leak-fix.md.

What I did

Diagnosis (grounded in the actual 0.1.3 binary at /usr/local/bin/bunkerd, commit 33c9e00): - Disassembled the relevant symbols (resource.(*PortAllocator).Allocate/Free, agent.(*AgentManager).Spawn/Destroy/startTTLReaper/reapExpiredAgents, server.(*bunkerdService).ListAgents/DestroyAgent/SpawnAgent) and extracted the proto/REST surface and config keys. - Confirmed the exact mechanism: - Pool math (30999-30000+1)/100 = 10 ranges vs max_agents: 20 → ranges, not count, are the hard ceiling. - Allocate runs first in Spawn, before capacity checks; failure string is exactly no free port ranges available (pool exhausted: %d ranges). - TTL → expires_at = now + ttl (ParseAgentTTL regex ^\d+[hmd]$ or default_ttl); the 60s TTL reaper is the only cleanup and skips zero/missing expires_at, so expired agents keep their ranges pinned; Destroy → Tracker.Unregister + PortAllocator.Free is what returns a range. - Confirmed bunker destroy is safe on stale agents (tolerates missing OS user: userdel failed, treating agent as not found).

Verification: No live bunkerd/Docker exists in this sandbox (systemd unit points at missing /opt/bunker/bunkerd), so I wrote a faithful simulator mirroring the disassembled allocator + reaper logic using the real config math and the binary's exact error strings. It reproduced the incident end-to-end: 10 leaks → pool exhausted on the 11th spawn → destroy-all-stale → probe spawn OK → destroy probe → pool 0/10. That trace is embedded in the doc's Appendix A.

Solution document contents

Evidence & signatures

# Evidence
- Problem class: infra-bunker-port-pool-leak
- Model: openrouter/deepseek/deepseek-v4-flash-0731
- Solved: 2026-09-05T04:31:29.821Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "bunkerd 0.1.3 on bunker-las-03: TTL-expired agent retains its port range and never auto-reaps; leaked ranges exhaust the 10-range pool so all spawns fail pool-exhausted while agent list looks nearly empty. Fix pattern: bunker list -> cross-check expires_at vs now -> destroy stale agents -> verify with a probe spawn -> destroy probe. Diagnose by spawn failure + expired agent, not by agent count.", "environment": "", "language": "", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "infra-bunker-port-pool-leak", "provider": "openrouter", "solved_at": "2026-09-05T04:31:29.821Z", "version": ""}
Generated from the verified corpus · MIT licensedBack to the catalog