Reworked logic of registering async requests in Session.m_outstandingRequests #152
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Problem description.
Keep alive problems on the client side are detected. This is happening due to m_outstandingRequests count limited as 10 + subscription count
and new keep alive requests are not sent if limit reached.
Bug repeating algorithm: session timeout interval set to 1 hour, subscription publishing interval set to 10 sec, session keepalive interval set to 1 sec. After connection was established turn off network adapter. After 15 failed reconnection attempts there should be 15 "hanged" requests in m_outstandingRequests, now turn on network adapter. Reached limit of m_outstandingRequests will prevent sending addidtional keepalive requests after session reconnecting and right after reconnection keep alive problems detected again. Reconnection starts again and so forth.
Root cause is that during reconnection BeginPublish requests are sent
, then immediately callback is called in another thread, where AsyncRequestCompleted is called. At this moment AsyncRequestStarted was not called yet and therefore dummy AsyncRequestState is addded to m_outstandingRequests
. Then inside BeginPublish Exception "HostNotFound" is thrown. TcpCLientChannel.cs, line 139
As result AsyncRequestStarted method never reached and dummy request added in AsyncRequestCompleted never removed from m_outstandingRequests.
To solve the problem it is proposed not to register requests as dummy if AsynRequestCompleted is called earlier than AsyncRequestStarted but instead just skip any registering. IAsyncResult.IsCompleted flag is always set True before calling completion callback (where AsyncRequestCompleted is called), so racing condition is not possible in AsyncRequestStarted. Latest mentioned fact regarding IsCompleted flag is checked in TcpAsyncOperation.cs and AsyncResultBase.cs files.
P.S. Proposed solution was tested in real Ua client application successfully.