Skip to content

bug(envd): PostInit spawns unbounded MMDS-poll goroutines — one per /init retry #3559

Description

@AdaAibaby

Summary

PostInit unconditionally spawns a new goroutine on every call to poll MMDS. The orchestrator drives /init via an infinite retry loop, so when MMDS is not immediately reachable, goroutines accumulate inside the microVM without bound.

Root Cause

packages/envd/internal/api/init.go lines 209-213:

go func() {
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
host.PollForMMDSOpts(ctx, a.mmdsChan, a.defaults.EnvVars)
}()

No guard prevents concurrent goroutine accumulation. initLock serialises body processing but the goroutine spawns after initLock.Release(1) so serialisation does not protect the spawn.

PollForMMDSOpts creates its own http.Client with DisableKeepAlives and ticks every 50ms issuing 2 HTTP requests per tick. Each goroutine lives up to 60 seconds.

Impact

At 100ms retry interval, 60 seconds of MMDS unavailability produces 600 concurrent goroutines, each making 40 connection-attempts/sec to 169.254.169.254 — 24000 TCP connections/sec total. This exhausts the VM ephemeral port range and can crash the envd control plane mid-resume.

Fix

Add an atomic.Bool guard to API struct and use CompareAndSwap in PostInit:

if a.mmdsPollRunning.CompareAndSwap(false, true) {
go func() {
defer a.mmdsPollRunning.Store(false)
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
host.PollForMMDSOpts(ctx, a.mmdsChan, a.defaults.EnvVars)
}()
}

Caps concurrent MMDS-poll goroutines at 1 while preserving re-poll across resume cycles.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions