Why should I wait for `isBound` when allocating random socket in Java?

121 Views Asked by At

Recently I had an issue with embedded-postgres library. I tried to manually pick a free port via

new ServerSocket(0).getLocalPort()

but I was hitting a race condition somewhere (my tests hanged on the second test suite startup).

Then I learned that the library has this capability (of using random port) itself and it didn't have the problem I had. I analyzed the source code and the only difference I found was that they do an additional check:

try (ServerSocket socket = new ServerSocket(0)) {
    while(!socket.isBound()) {
        Thread.sleep(50);
    }
    return socket.getLocalPort();
}

So after the port was randomized they wait until it is bound. Code I'm referring to.

I'd like to know why this code is there. My understanding of "binding" was that it's equal to "listening" on a given port, yet here it can't be the case, as this code runs before the server starts. In fact, the server will start (and bind itself) to this exact port. This makes me very confused.

1

There are 1 best solutions below

0
On BEST ANSWER

The code in the library is a fix to this issue which gives the reason as

..it appears that the EmbeddedPostgres#detectPort method may cause the issue as it does not wait for the socket to be bound before querying the port, leading ServerSocket#getLocalPort to return -1 as documented.

So the call to ServerSocket.getLocalPort() returns -1 if the socket is not bound, and apparently this may happen some time after a call to new ServerSocket(0), though it's unclear under what circumstances. So the code simply waits to make sure it's bound.

However the documentation doesn't say anywhere that new ServerSocket(0) doesn't return a bound socket. The javadoc for ServerSocket(int port) says "Creates a server socket, bound to the specified port.".

However they did have an issue, that's the only fix, and I suppose it resolved the issue...so just very unclear documentation in the JDK?


As for binding vs. listening. Binding is the part where you assign the address and port, it still needs to actively start accepting connections.