77e77fb481
The raw blocking fd had three lifecycle bugs: close() does not wake a thread blocked in recvfrom, the watchdog and the error path both closed the fd without coordination, and a closed fd number could be recycled to an unrelated connection that the lingering reader would then consume from and the second close would tear down. Wrapping the nonblocking fd in os.File gives poller-based reads that Close wakes, idempotent close, and no reuse while a read is in flight.