diff --git a/libtest/port.cc b/libtest/port.cc index 54dcffe61..517317adc 100644 --- a/libtest/port.cc +++ b/libtest/port.cc @@ -232,7 +232,11 @@ in_port_t get_free_port() } all_socket_fd.last_port= ret_port; - release_port(ret_port); + + // Deliberately leave the reservation socket bound (not released) so the + // port stays unavailable to other processes' get_free_port() calls until + // the caller explicitly release_port()s it, e.g. once its server is + // confirmed listening. See libtest::Server::start(). return ret_port; } diff --git a/libtest/server.cc b/libtest/server.cc index f644465bf..ad243238e 100644 --- a/libtest/server.cc +++ b/libtest/server.cc @@ -229,7 +229,14 @@ bool Server::start() hostname(), port(), "Could not build command()"); } - libtest::release_port(_port); + // Hold the port reservation (acquired via get_free_port()) until start() + // returns by any path -- success, ping timeout, or exception -- so no + // other concurrently-running test process's get_free_port() can grab + // _port while this server is still starting up. + struct PortReservation { + in_port_t port; + ~PortReservation() { libtest::release_port(port); } + } port_reservation{_port}; Application::error_t ret; if (Application::SUCCESS != (ret= _app.run()))