Skip to content
Open
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 @@ -252,25 +252,116 @@ private void connect() {
}

private void pollConnectFuture() {
ConnectFuture future = connectFuture;
if (future == null) {
return;
}

try {
connectFuture.awaitUninterruptibly(CONNECT_POLL_TIMEOUT);
if (connectFuture.getSession() != null) {
ioSession = connectFuture.getSession();
future.awaitUninterruptibly(CONNECT_POLL_TIMEOUT);

IoSession session = future.getSession();
if (session != null) {
ioSession = session;
connectionFailureCount = 0;
nextSocketAddressIndex = 0;
lastConnectTime = System.currentTimeMillis();
connectFuture = null;
} else {
fixSession.getLog().onEvent(
return;
}

Throwable exception = future.getException();
if (exception != null) {
connectFuture = null;

/*
* Do not call cancelPendingConnectAttempt() here.
* The future already completed with an exception.
* Just release our reference to the connector.
*/

handleConnectException(exception);
return;
}
long now = System.currentTimeMillis();
long pendingMillis = now - lastReconnectAttemptTime;

fixSession.getLog().onEvent(
"Pending connection not established after "
+ (System.currentTimeMillis() - lastReconnectAttemptTime)
+ pendingMillis
+ " ms.");

long maxPendingMillis = connectTimeoutMillis;

if (maxPendingMillis > 0 && pendingMillis >= maxPendingMillis) {
fixSession.getLog().onEvent(
"Pending connection exceeded max wait of "
+ maxPendingMillis
+ " ms; cancelling connect attempt and allowing reconnect."
);

try {
cancelAndResetPendingConnectAttempt(future);
} catch (Throwable cancelException) {
fixSession.getLog().onWarnEvent(
"Exception while cancelling pending connect future: "
+ cancelException
);
}

/*
* Important:
* Reset reconnect timing from this failure moment.
* Without this, the next timer tick may reconnect immediately
* because pendingMillis has already exceeded ReconnectInterval.
*/
lastConnectTime = now;
lastReconnectAttemptTime = now;

handleConnectException(new IOException(
"Connect attempt exceeded max pending time of " + maxPendingMillis + " ms"
));
}

} catch (Throwable e) {
handleConnectException(e);
}
}

private void cancelAndResetPendingConnectAttempt(ConnectFuture future) throws ConfigError, GeneralSecurityException {
try {
if (future != null) {
IoSession session = future.getSession();
if (session != null) {
session.closeNow();
}

future.cancel();
}
} catch (Throwable e) {
fixSession.getLog().onWarnEvent(
"Exception while cancelling pending connect future: " + e
);
}

if (ioConnector instanceof ProxyConnector) {
try {
((ProxyConnector) ioConnector).cancelConnectFuture();
} catch (Throwable e) {
fixSession.getLog().onWarnEvent(
"Exception while cancelling proxy connector future: " + e
);
}

try {
setupIoConnector();

@chrjohn chrjohn Jul 6, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this only done on a ProxyConnector? I assume because it has some internal state that needs to be handled differently? Maybe add some explanation?
Edit: I'm still thinking about if this could conflict with the dispose-logic.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got this exception when reused IoConnector for proxy.
java.lang.IllegalStateException: handler cannot be set while the service is active.
at org.apache.mina.core.service.AbstractIoService.setHandler(...)
at org.apache.mina.proxy.ProxyConnector.connect0(...)

This exception does not occure when reusing the IoConnector in non-proxy connection timeout, where the server does not reply TCP SYN.
by explanation, you mean adding code comment?

} catch (Throwable e) {
fixSession.getLog().onErrorEvent("Exception while recreating proxy connector: " + e);
throw e;
}
}
}

private void handleConnectException(Throwable e) {
++connectionFailureCount;
SocketAddress socketAddress = socketAddresses[getCurrentSocketAddressIndex()];
Expand Down
Loading
Loading