The move away from libevent introduced a small regression in this regard. In #36299, we switched the timeout to apply per socket wait, but continued on to another socket wait in case of timeout, instead of returning. See commit message for details.
In general, we also shouldn't ignore Sock::Wait's errors and timeouts by silently retrying forever.
Fix these issues by returning instead when Sock::Wait times out or returns an error. Tentative bot functional test for this in second commit that appears to be robust enough.