Avoid flaky test failures by retrying on local port conflicts (#15818)

This test obtains an available port number by calling `TCPServer.new`,
then closes it and passes the same port number as `local_port` to `TCPSocket.new`.

However, `TCPSocket.new` could occasionally fail with `Errno::EADDRINUSE`
at the bind(2) step.
I believe this happens when tests are run in parallel and another process
on the same host happens to bind the same port in the short window between
closing the `TCPServer` and calling `TCPSocket.new`.

To address this race condition, the test now retries with a newly selected
available port when such a conflict occurs.
This commit is contained in:
Misaki Shioi 2026-01-08 09:41:42 +09:00 committed by GitHub
parent 950ffa90b7
commit 080d66beca
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
Notes: git 2026-01-08 00:42:10 +00:00
Merged-By: shioimm <shioi.mm@gmail.com>

View File

@ -53,14 +53,23 @@ describe :tcpsocket_new, shared: true do
end
it "connects to a server when passed local_host and local_port arguments" do
server = TCPServer.new(SocketSpecs.hostname, 0)
retries = 0
max_retries = 3
begin
available_port = server.addr[1]
ensure
server.close
retries += 1
server = TCPServer.new(SocketSpecs.hostname, 0)
begin
available_port = server.addr[1]
ensure
server.close
end
@socket = TCPSocket.send(@method, @hostname, @server.port,
@hostname, available_port)
rescue Errno::EADDRINUSE
raise if retries >= max_retries
retry
end
@socket = TCPSocket.send(@method, @hostname, @server.port,
@hostname, available_port)
@socket.should be_an_instance_of(TCPSocket)
end