Skip to content

Commit

Permalink
[TESTS] Set SO_LINGER and SO_REUSEADDR on the mock socket (#34211)
Browse files Browse the repository at this point in the history
In SessionFactoryLoadBalancingTests#testRoundRobinWithFailures()
we kill ldap servers randomly and immediately bind to that port
connecting to mock server socket. This is done to avoid someone else
listening to this port. As the creation of mock socket and binding to the
port is immediate, sometimes the earlier socket would be in TIME_WAIT state
thereby having problems with either bind or connect.
This commit sets the SO_REUSEADDR explicitly to true and also sets
the linger on time to 0(as we are not writing any data) so as to
allow re-use of the port and close immediately.

Note: I could not find other places where this might be problematic
but looking at test runs and netstat output I do see lot of sockets
in TIME_WAIT. If we find that this needs to be addressed we can
wrap ServerSocketFactory to set these options and use that with in
memory ldap server configuration during tests.

Closes #32190
  • Loading branch information
bizybot authored and kcm committed Oct 30, 2018
1 parent 18b2267 commit 342c1e9
Showing 1 changed file with 15 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.sdk.LDAPConnection;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.common.SuppressForbidden;
import org.elasticsearch.common.settings.SecureString;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.util.concurrent.ThreadContext;
Expand All @@ -17,6 +18,7 @@
import org.elasticsearch.test.junit.annotations.TestLogging;
import org.elasticsearch.threadpool.TestThreadPool;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xpack.core.common.socket.SocketAccess;
import org.elasticsearch.xpack.core.security.authc.RealmConfig;
import org.elasticsearch.xpack.core.security.authc.ldap.support.LdapSearchScope;
import org.elasticsearch.xpack.core.ssl.SSLService;
Expand All @@ -25,6 +27,7 @@

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Arrays;
Expand Down Expand Up @@ -112,7 +115,7 @@ public void testRoundRobinWithFailures() throws Exception {
// of the ldap server and the opening of the socket
logger.debug("opening mock server socket listening on [{}]", port);
Runnable runnable = () -> {
try (Socket socket = new MockSocket(InetAddress.getByName("localhost"), mockServerSocket.getLocalPort(), local, port)) {
try (Socket socket = openMockSocket(local, mockServerSocket.getLocalPort(), local, port)) {
logger.debug("opened socket [{}]", socket);
latch.countDown();
closeLatch.await();
Expand Down Expand Up @@ -149,6 +152,17 @@ public void testRoundRobinWithFailures() throws Exception {
}
}

@SuppressForbidden(reason = "Allow opening socket for test")
private MockSocket openMockSocket(InetAddress remoteAddress, int remotePort, InetAddress localAddress, int localPort)
throws IOException {
final MockSocket socket = new MockSocket();
socket.setReuseAddress(true); // allow binding even if the previous socket is in timed wait state.
socket.setSoLinger(true, 0); // close immediately as we are not writing anything here.
socket.bind(new InetSocketAddress(localAddress, localPort));
SocketAccess.doPrivileged(() -> socket.connect(new InetSocketAddress(localAddress, remotePort)));
return socket;
}

public void testFailover() throws Exception {
assumeTrue("at least one ldap server should be present for this test", ldapServers.length > 1);
logger.debug("using [{}] ldap servers, urls {}", ldapServers.length, ldapUrls());
Expand Down

0 comments on commit 342c1e9

Please sign in to comment.