Skip to content

Commit 81c4eea

Browse files
committed
Fix port collisions in adapter_lint
In order to 'reserve' a free TCP Server port, we create a TCPServer, take a note of its port number, and then immediately close it. We'd then ask our adapter to use the port we just finished with via that adapter's configuration. While this isn't a particularly safe way of 'reserving' a port, it's the best we can do with heterogeneous adapters that have a one-way config method. However, this would cause intermittent test failures when our 'canary' socket did not get out of the way in time for an adapter to bind its server. Socket#close does not actually block until the socket is closed at OS level, it just frees the Ruby handle to it. Actually waiting for the socket to become free or garbage-collecting it to force the issue is counterproductive – we'd need to poll the port or run a full GC, which would take more time than a simple sleep. Additionally, the sleep needs to be tuned so that tests are not unduly slowed by it – too quick and we'll see failures, too slow and our builds will reflect it.
1 parent 07f02c2 commit 81c4eea

File tree

1 file changed

+13
-1
lines changed

1 file changed

+13
-1
lines changed

lib/webmachine/spec/adapter_lint.rb

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,19 @@
55
attr_accessor :client
66

77
let(:address) { "127.0.0.1" }
8-
let(:port) { s = TCPServer.new(address, 0); p = s.addr[1]; s.close; p }
8+
let(:port) do
9+
s = TCPServer.new(address, 0)
10+
p = s.addr[1]
11+
s.close # This does not close the socket at OS level, just frees from Ruby.
12+
# The socket will be in TIME_WAIT http://www.ssfnet.org/Exchange/tcp/tcpTutorialNotes.html
13+
# "The main thing to recognize about connection teardown is that a connection in
14+
# the TIME_WAIT state cannot move to the CLOSED state until it has waited for two times
15+
# the maximum amount of time an IP datagram might live in the Inter net."
16+
17+
sleep(0.005) # This is just about the best we can do. Any more slows the tests,
18+
# any less and we get intermittent silent port collisions
19+
p
20+
end
921

1022
let(:application) do
1123
application = Webmachine::Application.new

0 commit comments

Comments
 (0)