Skip to content

[#125] Do not resend the initial CONNECTOR_INFO request when shutdown() cancelled it - #129

Open
vharseko wants to merge 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issue-125-no-retry-on-shutdown
Open

vharseko wants to merge 1 commit into
OpenIdentityPlatform:masterfrom
vharseko:issue-125-no-retry-on-shutdown

Conversation

@vharseko

Copy link
Copy Markdown
Member

Fixes #125

Problem

The failure branch attached to the initial CONNECTOR_INFO request in WebSocketConnectionGroup.handshakeComplete() resubmitted the request on any failure, cancellation included. shutdown() cancels every pending remote request with getPromise().cancel(true); PromiseImpl runs the listeners on the cancelling thread and routes CANCELLED to the onException function, so the retry ran synchronously inside shutdown()'s loop over remoteRequests - before principalIsShuttingDown() removed the sockets - and was sent over the closing connection and registered in the group being torn down.

Two refinements to the issue text, found while verifying it:

  • When the initial request is the only pending entry (the usual case: shutdown right after handshake), the ConcurrentSkipListMap iterator has already advanced past the end, so the retry is not visited by the shutdown loop and stays registered and pending in the dead group. The "extra CONNECTOR_INFO + CancelOpRequest on the wire" outcome happens only when other requests are pending after it.
  • On the receiving side a ControlRequest is handled synchronously without a LocalRequest, so the stray CancelOpRequest only parks a pendingCancels entry for 60 s; the cost is one needless serializeLegacy of all connector infos and a response into a closing socket.

Fix

The retry is skipped when the first request's promise is cancelled. The promise state is checked rather than the exception type because RemoteOperationRequest.createCancellationException returns a failed remote cancel's exception as-is (e.g. ConnectorIOException when the CancelOpRequest could not be sent), so CancellationException is not a reliable marker.

Test

WebSocketConnectionGroupShutdownTest: a recording socket stub and a group subclass exposing remoteRequests; handshake + handshakeComplete() send one ControlRequest, then principalIsShuttingDown(). Before the fix: a second ControlRequest is sent during shutdown and the retry stays in remoteRequests. After: one ControlRequest, one CancelOpRequest, remoteRequests empty.

Independent of #124 (the test uses an already-sent request, so it does not depend on the promise existing before the send).

…equest when shutdown() cancelled it

The failure branch attached to the initial 'CONNECTOR_INFO' request in
WebSocketConnectionGroup.handshakeComplete() resubmitted the request on any
failure, cancellation included. shutdown() cancels every pending remote
request with getPromise().cancel(true); PromiseImpl runs the listeners on the
cancelling thread and routes CANCELLED to the onException function, so the
retry ran synchronously inside shutdown()'s loop - before
principalIsShuttingDown() removed the sockets - and was sent over the
closing connection and registered in the group being torn down. When the
initial request was the only pending entry, the ConcurrentSkipListMap
iterator had already advanced past the end and the retry stayed registered
and pending in the dead group.

The retry is now skipped when the first request's promise is cancelled. The
promise state is checked rather than the exception type because
RemoteOperationRequest.createCancellationException returns a failed remote
cancel's exception as-is.

Fixes OpenIdentityPlatform#125
@vharseko vharseko added bug Something isn't working framework OpenICF-java-framework java Pull requests that update java code tests Test additions or fixes concurrency Races, locking and thread-safety fixes labels Sep 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working concurrency Races, locking and thread-safety fixes framework OpenICF-java-framework java Pull requests that update java code tests Test additions or fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

handshakeComplete() resends the initial CONNECTOR_INFO request while the group is shutting down

1 participant