Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
*
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
* Portions Copyrighted 2026 3A Systems, LLC.
*/
package org.opends.server.protocols.ldap;

Expand Down Expand Up @@ -183,6 +184,14 @@ public void run()
*/
private final Object waitListen = new Object();

/**
* Condition predicate for {@link #waitListen}: set once the selector thread
* has attempted to open the listen channels (successfully or not). Guarded
* by the {@link #waitListen} monitor; protects the start method against
* spurious wakeups.
*/
private boolean listenAttempted;

/** The friendly name of this connection handler. */
private String friendlyName;

Expand Down Expand Up @@ -814,12 +823,16 @@ public void start()

try
{
waitListen.wait();
while (!listenAttempted)
{
waitListen.wait();
}
}
catch (InterruptedException e)
{
// If something interrupted the start its probably better
// to return ASAP.
Thread.currentThread().interrupt();
}
}
}
Expand Down Expand Up @@ -859,6 +872,7 @@ public void run()
synchronized (waitListen)
{
starting = false;
listenAttempted = true;
waitListen.notify();
}
}
Expand All @@ -882,6 +896,7 @@ public void run()
// should be notified and resume its work in any cases.
synchronized (waitListen)
{
listenAttempted = true;
waitListen.notify();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* Copyright 2006-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2016 ForgeRock AS.
* Portions Copyright 2013 Manuel Gaupp
* Portions Copyright 2018-2025 3A Systems, LLC
* Portions Copyright 2018-2026 3A Systems, LLC
*/
package org.opends.server;

Expand Down Expand Up @@ -68,6 +68,7 @@
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.logging.ConsoleHandler;
import java.util.logging.Handler;
import java.util.logging.LogManager;
Expand Down Expand Up @@ -119,6 +120,7 @@
import org.opends.server.util.BuildVersion;
import org.opends.server.util.DynamicConstants;
import org.opends.server.util.LDIFReader;
import org.opends.server.util.TestTimer;

import com.forgerock.opendj.util.OperatingSystem;

Expand Down Expand Up @@ -327,6 +329,7 @@ public static void startServer() throws Exception
setupLoggers();
writeBuildInfoFile();
server.start();
waitForLdapListener();
assertTrue(InvocationCounterPlugin.startupCalled());
// Save config.ldif for when we restart the server
backupServerConfigLdif();
Expand Down Expand Up @@ -607,6 +610,7 @@ public static synchronized void restartServer()
restoreServerConfigLdif();

server.start();
waitForLdapListener();

clearJEBackends();
initializeTestBackend(true);
Expand All @@ -625,6 +629,38 @@ public static synchronized void restartServer()
}
}

/**
* Waits until the LDAP connection handler actually accepts TCP connections.
* {@code LDAPConnectionHandler.start()} may return before the listen
* channel is bound (e.g. after an early wakeup of its wait-for-listen
* handshake), so the very first connection made right after a server
* (re)start could otherwise be refused.
*/
private static void waitForLdapListener() throws Exception
{
new TestTimer.Builder()
.maxSleep(10, TimeUnit.SECONDS)
.sleepTimes(100, TimeUnit.MILLISECONDS)
.toTimer()
.repeatUntilSuccess(new TestTimer.CallableVoid()
{
@Override
public void call() throws Exception
{
try (Socket s = new Socket())
{
s.connect(new InetSocketAddress("127.0.0.1", getServerLdapPort()), 500);
}
catch (IOException e)
{
// repeatUntilSuccess() only retries on assertion errors.
throw new AssertionError("LDAP port " + getServerLdapPort()
+ " is not accepting connections yet", e);
}
}
});
}

/**
* Returns the embedded server used for tests.
*
Expand Down
Loading