#550

fix(mdns): keep tracking republished hostnames so stale adverts get removed

Openakshitkrnagpalwants to merge intofrom

Fixes #373.

Problem

Each dns-sd -P (or avahi-publish-address) child removes its hostname from activePublishers when it exits, without checking which child the entry belongs to:

child.on("exit", () => {
  activePublishers.delete(hostname);
});

Two paths start a replacement before the old child has exited:

  • Port change in reloadRoutes: unpublish(host) then publish(host).
  • LAN IP change in updateLanIp: cleanupAll() then publishCachedRoutes(). This runs often on machines with Ethernet and Wi-Fi on the same LAN, on short DHCP leases, and after sleep/wake.

The old child's exit fires after the replacement is registered and deletes the replacement's entry. The replacement keeps running but nothing tracks it, so:

  • After a LAN IP change, the next change can't kill it, and it keeps answering with the old IP. This is the symptom in #373.
  • When its route is removed, unpublish() finds nothing to kill. The hostname stays advertised and LAN clients land on the proxy's "No app registered" 404.

Fix

The exit and error handlers now remove the entry only if the map still points at the exiting child.

Tests

mdns.test.ts gets cases that replace spawn with a fake child and replay both sequences (port change, and cleanupAll plus republish) with a late exit/error from the old child. Two of the new tests fail on main and pass with this change. pnpm lint, pnpm type-check and Prettier pass.

Not covered here

If the proxy dies hard (crash or SIGKILL), its publishers outlive it, because they are never told to stop. That needs a separate change (for example, reaping leftover publishers on startup).

🤖 Generated with Claude Code

Activity

2
vercel[bot]9d ago

@akshitkrnagpal is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.