[QFJ-484] Session responder lock change inadequate Created: 17/Nov/09  Updated: 29/Apr/11  Resolved: 29/Apr/11

Status: Closed
Project: QuickFIX/J
Component/s: Engine
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Default
Reporter: James Olsen Assignee: Unassigned
Resolution: Won't Fix Votes: 0
Labels: None

Attachments: Text File QFJ-484(1_5_0).patch     Text File QFJ-484.patch    
Issue Links:
Relates
is related to QFJ-421 Session responder lock is too restric... Closed

 Description   

Using a synchronized block can result in a thread being starved of access to the responder. This should be changed to use a Lock with fair semantics.

Starvation was observed in a scenario using SocketSynchronousWrites=Y where a slow consumer could not be disconnected because the message writing thread kept re-obtaining the monitor.



 Comments   
Comment by James Olsen [ 17/Nov/09 ]

Relates to change proposed by QFJ-421.

Comment by James Olsen [ 17/Nov/09 ]

No option to attach patch, so will try in-lining:

Index: core/src/main/java/quickfix/Session.java
===================================================================
— core/src/main/java/quickfix/Session.java (revision 926)
+++ core/src/main/java/quickfix/Session.java (working copy)
@@ -27,6 +27,8 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;

import quickfix.Message.Header;
import quickfix.field.BeginSeqNo;
@@ -231,7 +233,7 @@

private boolean enabled;

  • private final String responderSync = "SessionResponderSync";
    + private final Lock responderSync = new ReentrantLock(true);
    // @GuardedBy(responderSync)
    private Responder responder;

@@ -330,19 +332,25 @@

  • @param responder a responder implementation
    */
    public void setResponder(Responder responder) {
  • synchronized (responderSync) {
    + responderSync.lock();
    + try
    Unknown macro: { this.responder = responder; if (responder != null) { stateListener.onConnect(); } else { stateListener.onDisconnect(); }+ }

    finally

    { + responderSync.unlock(); }
    }

    public Responder getResponder() {
    - synchronized (responderSync) {
    + responderSync.lock();
    + try { // FIXME why this???? return responder; + } finally {+ responderSync.unlock(); }

    }

@@ -1436,13 +1444,16 @@

  • @throws IOException IO error
    */
    public void disconnect() throws IOException {
  • synchronized (responderSync) {
    + responderSync.lock();
    + try
    Unknown macro: { if (!hasResponder()) { return; } getLog().onEvent("Disconnecting"); responder.disconnect(); setResponder(null);+ }

    finally

    { + responderSync.unlock(); }

    boolean logonReceived = state.isLogonReceived();
    @@ -1778,13 +1789,16 @@

    private boolean send(String messageString) {
    getLog().onOutgoing(messageString);
    - synchronized (responderSync) {
    + responderSync.lock();
    + try {
    if (!hasResponder()) { getLog().onEvent( "Attempt to send while not connected (message stored until connected)."); return false; }
    return getResponder().send(messageString);
    + } finally {+ responderSync.unlock(); }

    }

Comment by James Olsen [ 16/Feb/10 ]

Attached QFJ-484.patch based on using a re-entrant lock as discussed above and the change recommended by Parwinder Sekhon at http://www.quickfixj.org/jira/browse/QFJ-433?focusedCommentId=11014&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_11014

Parwdiner's change is critical when using synchronous writes when you have multiple sessions running.

Comment by James Olsen [ 17/Jan/11 ]

Copy of patch as applied to 1_5_0 Session source.

Comment by Eric Deshayes [ 28/Apr/11 ]

committed on integration branch rev #1024

Comment by Eric Deshayes [ 29/Apr/11 ]

After discussion, the usage of Reentrant Lock would likely cause some throughput/latency performance.
Also, the scenario that lead to that issue is not a common usecase (very slow file writing operation).
However, it highlighted a regression following the issue QFJ-421 which has been reopened.

Generated at Sat May 18 18:41:18 UTC 2024 using JIRA 7.5.2#75007-sha1:9f5725bb824792b3230a5d8716f0c13e296a3cae.