Skip to content

A restarted daemon can hand one emulator's console port to another device #52

Description

@V3RON

Problem

Found while implementing #14, deliberately left out of that PR (#50) because it changes the boot path rather than the lease payload.

PortAllocator (src/drivers/android/index.ts) tracks reservations in an in-memory #reserved set, and picks a free port by unioning that set with the ports it can see in adb devices:

const unavailable = new Set([...this.#reserved, ...portsFromAdbDevices(result.stdout)]);

adb devices only lists live emulators. A device in shutdown is not live, and its port lives only in #reserved — which dies with the daemon process.

So, after a restart:

  1. Device A is shutdown, with port: 5554 persisted in its driverData.
  2. The daemon restarts. #reserved is empty.
  3. Device B is provisioned. adb devices shows nothing on 5554, so B is allocated 5554 and boots on it.
  4. Device A is asked for next. #startEmulator passes -port 5554, which B holds.

-port pins the console port rather than falling back to a free one, so step 4 is a boot failure, not a silent mislanding. That failure mode is at least loud — but it strands a registered device that has nothing wrong with it, and the collision only surfaces at lease time, when an agent is waiting.

Why now

Not new, and not caused by #14 — but #14's address makes it easier to reason about, since a device's reachable address is now persisted and re-read on every makeReady.

Options

Not obviously one right answer, hence an issue rather than a patch:

  • Seed reservations at startup. AndroidDriver could reserve the ports of every registry-known device when it starts, so a shutdown device's port is not handed out. Cleanest fix conceptually; needs the driver to learn the registry's device list at construction, which is a boundary question (listManaged() sees only live emulators, so it isn't enough on its own).
  • Verify the port before each boot. Re-check the reserved port at every genuine boot and move to a fresh one when it is taken. I drafted this while working on feat(driver): surface the platform address and complete the lease payload #50 and backed it out: it works, but it costs an adb devices call per boot and reads as a workaround for a reservation that should not have been lost.
  • Do nothing yet, but fail better. Detect the collision at boot and produce a clear driver error naming the device that holds the port, instead of an emulator startup failure.

Notes

Acceptance criteria

  • A device provisioned after a restart is never allocated a port that a registry-known shutdown device is holding.
  • Regression test with a scripted ProcessRunner covering the restart → provision → boot sequence.
  • pnpm check green.

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

    bug:triageAn agent may reproduce it and write the triage report.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions