sailfin
  1. sailfin
  2. SAILFIN-1883

DialogLifeCycle leaves dialog locked too long

    Details

    • Type: Bug Bug
    • Status: Resolved
    • Priority: Major Major
    • Resolution: Won't Fix
    • Affects Version/s: 2.0
    • Fix Version/s: milestone 1
    • Component/s: sip_container
    • Labels:
      None
    • Environment:

      Operating System: All
      Platform: All

    • Issuezilla Id:
      1,883

      Description

      When a dialoglifecycle is created, it locks the dialog fragment when the unit of
      work is initialized (initUnitOfWork). The dialog fragment is not unlocked until
      a much later time when the dialog cleaner runs and removes the dialog fragment.

      Consider an Invite transaction – the client sends INVITE and then the ACK,
      which ends the transaction. At this point the DF is replicated – but it is
      still locked. So after a failure, the DF can not actually be used because the
      saved version is locked. Clients attempting to use that session will get an
      endless stream of 503 responses because the container is waiting for the session
      to be unlocked.

      With the failure, the dialog cleaner would have come along and unlocked the
      session so that it could be reused. But that doesn't save the session, so it
      doesn't help the error case. Even so, it is too late by that time; replication
      can be asynchronous, but this stretches the window of vulnerability to the
      invocation time between invocations of the dialog cleaner.

      I have tested what happens when the DF is not locked in initUnitOfWork. Because
      the DF is locked when it is actually added to the ReplicationUnitOfWork, that
      might be an acceptable solution. At any rate, it solved the issue with the
      remote lock exceptions after a failure and restart. But I am way out of my depth
      here to know whether that is a generally acceptable solution.

        Issue Links

          Activity

          Hide
          erikvandervelden added a comment -

          Adding myself to the CC.

          Please describe which case you are talking about, proxy, UAC, UAS?

          The last time I was looking at this I've made some small (untested!) changes
          that should improve the unlocking in some cases, but this does not help with the
          general ACK case.

          Have a look to see if they are useful.

          Index: InviteClientTransaction.java
          ===================================================================
          RCS file:
          /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/InviteClientTransaction.java,v
          retrieving revision 1.15
          diff -u -r1.15 InviteClientTransaction.java
          — InviteClientTransaction.java 26 Sep 2008 10:44:04 -0000 1.15
          +++ InviteClientTransaction.java 12 Aug 2009 10:34:24 -0000
          @@ -177,6 +177,10 @@

          // could get 2xx from same or different end-points,
          // multiple 2xx responses may arraive
          +
          + // XXX could we do some magic here; like re-lock the dialog
          + // on the next received 2xx response
          +
          break;

          case TERMINATED:
          @@ -497,6 +501,9 @@
          _timerA = null;
          }

          + if (resp.getDialog() != null)

          { + resp.getDialog().getDialogLifeCycle().onTransactionRemoved(_transactionId, true); // TODO true or false + }

          _state = COMPLETED;
          _timerD = _timerService.createTimer(this, 64 * T1, TimerD);
          } else

          { @@ -522,12 +529,17 @@ }

          }

          • // Start timer RemoveTransaction
          • long delay = 64 * T1;
          • _timerRemoveTransaction = _timerService.createTimer(this, delay,
          • TimerRemoveTransaction);
          • prolongDialogSet(delay);
          • _state = ESTABLISHED;
            + if (!_reliableTransport && _request.isInitial()) { + // Start timer RemoveTransaction + long delay = 64 * T1; + _timerRemoveTransaction = _timerService.createTimer(this, delay, + TimerRemoveTransaction); + prolongDialogSet(delay); + _state = ESTABLISHED; + }

            else

            { + // safe to terminate since we do not expect retransmissions + terminate(); + }

            }

          private void toPending()

          { Index: InviteServerTransaction.java =================================================================== RCS file: /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/InviteServerTransaction.java,v retrieving revision 1.18 diff -u -r1.18 InviteServerTransaction.java --- InviteServerTransaction.java 6 Apr 2009 17:51:26 -0000 1.18 +++ InviteServerTransaction.java 12 Aug 2009 10:34:24 -0000 @@ -100,11 +100,16 @@ // occur since this charset is mandatory to exist. }

          + // NOTWORKING: handleCancelTrigger(_response);
          + // System.out.println("EVDV: pushing myself");
          _response.popDispatcher().dispatch(_response);
          }

          synchronized boolean handle(SipServletRequestImpl req) {
          if (req.getMethod().equals("ACK") && (_state == COMPLETED))

          { + // this is the hop-ACK! + // the ACK for 2xx responses is sent to the application and does NOT influence this transaction + // but it does confirm the dialog... toConfirmed(); }

          else if ((_response != null) &&
          ((_state == PROCEEDING) || (_state == COMPLETED)))

          { @@ -160,7 +165,7 @@ }

          else if (status == 2)

          { terminate(); }

          else

          { - toCompleted(); // 3xx to 6xx + toCompleted(resp); // 3xx to 6xx }

          break;
          @@ -264,13 +269,17 @@
          }
          }

          • private void toCompleted() {
            + private void toCompleted(SipServletResponseImpl resp) {
            stopCancel();
            _timerH = _timerService.createTimer(this, 64 * T1, TimerH);
            _state = COMPLETED;

          if (!_reliableTransport) {
          _timerG = _timerService.createTimer(this, T1, TimerG);
          +
          + if (resp.getDialog() != null)

          { + resp.getDialog().getDialogLifeCycle().onTransactionRemoved(_transactionId, false); // TODO true or false + }

          }
          }

          Index: NonInviteServerTransaction.java
          ===================================================================
          RCS file:
          /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/NonInviteServerTransaction.java,v
          retrieving revision 1.10
          diff -u -r1.10 NonInviteServerTransaction.java
          — NonInviteServerTransaction.java 16 Jun 2009 07:54:41 -0000 1.10
          +++ NonInviteServerTransaction.java 12 Aug 2009 10:34:24 -0000
          @@ -219,6 +219,10 @@
          _timerJ = _timerService.createTimer(this, 64 * T1, TimerJ);
          _response.setNeedSerialization(true);
          // optimization during timerJ
          + // Make sure dialog UOW is finished ASAP
          + if (getDialog() != null)

          { + getDialog().getDialogLifeCycle().onTransactionRemoved(getTransactionId(), false); // true or false? + }

          clearRequest();
          } else {
          _state = TERMINATED; // TimerJ = 0
          Index: Transaction.java
          ===================================================================
          RCS file:
          /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/Transaction.java,v
          retrieving revision 1.18
          diff -u -r1.18 Transaction.java
          — Transaction.java 28 Jul 2009 05:12:49 -0000 1.18
          +++ Transaction.java 12 Aug 2009 10:34:24 -0000
          @@ -102,7 +102,7 @@
          static long T4 = _transactionManager.getTimerT4();
          protected TransactionState _state;
          protected String _transactionId;

          • private SipServletRequestImpl _request;
            + protected SipServletRequestImpl _request;
            protected boolean _reliableTransport = true;
            private long _transactionStartedTimestamp = 0;
            private long _lastAccessTimestamp = 0;

          BTW, the 503 response is not endless, there is a retry-after and the stream
          should stop after 32 seconds...

          Show
          erikvandervelden added a comment - Adding myself to the CC. Please describe which case you are talking about, proxy, UAC, UAS? The last time I was looking at this I've made some small (untested!) changes that should improve the unlocking in some cases, but this does not help with the general ACK case. Have a look to see if they are useful. Index: InviteClientTransaction.java =================================================================== RCS file: /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/InviteClientTransaction.java,v retrieving revision 1.15 diff -u -r1.15 InviteClientTransaction.java — InviteClientTransaction.java 26 Sep 2008 10:44:04 -0000 1.15 +++ InviteClientTransaction.java 12 Aug 2009 10:34:24 -0000 @@ -177,6 +177,10 @@ // could get 2xx from same or different end-points, // multiple 2xx responses may arraive + + // XXX could we do some magic here; like re-lock the dialog + // on the next received 2xx response + break; case TERMINATED: @@ -497,6 +501,9 @@ _timerA = null; } + if (resp.getDialog() != null) { + resp.getDialog().getDialogLifeCycle().onTransactionRemoved(_transactionId, true); // TODO true or false + } _state = COMPLETED; _timerD = _timerService.createTimer(this, 64 * T1, TimerD); } else { @@ -522,12 +529,17 @@ } } // Start timer RemoveTransaction long delay = 64 * T1; _timerRemoveTransaction = _timerService.createTimer(this, delay, TimerRemoveTransaction); prolongDialogSet(delay); _state = ESTABLISHED; + if (!_reliableTransport && _request.isInitial()) { + // Start timer RemoveTransaction + long delay = 64 * T1; + _timerRemoveTransaction = _timerService.createTimer(this, delay, + TimerRemoveTransaction); + prolongDialogSet(delay); + _state = ESTABLISHED; + } else { + // safe to terminate since we do not expect retransmissions + terminate(); + } } private void toPending() { Index: InviteServerTransaction.java =================================================================== RCS file: /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/InviteServerTransaction.java,v retrieving revision 1.18 diff -u -r1.18 InviteServerTransaction.java --- InviteServerTransaction.java 6 Apr 2009 17:51:26 -0000 1.18 +++ InviteServerTransaction.java 12 Aug 2009 10:34:24 -0000 @@ -100,11 +100,16 @@ // occur since this charset is mandatory to exist. } + // NOTWORKING: handleCancelTrigger(_response); + // System.out.println("EVDV: pushing myself"); _response.popDispatcher().dispatch(_response); } synchronized boolean handle(SipServletRequestImpl req) { if (req.getMethod().equals("ACK") && (_state == COMPLETED)) { + // this is the hop-ACK! + // the ACK for 2xx responses is sent to the application and does NOT influence this transaction + // but it does confirm the dialog... toConfirmed(); } else if ((_response != null) && ((_state == PROCEEDING) || (_state == COMPLETED))) { @@ -160,7 +165,7 @@ } else if (status == 2) { terminate(); } else { - toCompleted(); // 3xx to 6xx + toCompleted(resp); // 3xx to 6xx } break; @@ -264,13 +269,17 @@ } } private void toCompleted() { + private void toCompleted(SipServletResponseImpl resp) { stopCancel(); _timerH = _timerService.createTimer(this, 64 * T1, TimerH); _state = COMPLETED; if (!_reliableTransport) { _timerG = _timerService.createTimer(this, T1, TimerG); + + if (resp.getDialog() != null) { + resp.getDialog().getDialogLifeCycle().onTransactionRemoved(_transactionId, false); // TODO true or false + } } } Index: NonInviteServerTransaction.java =================================================================== RCS file: /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/NonInviteServerTransaction.java,v retrieving revision 1.10 diff -u -r1.10 NonInviteServerTransaction.java — NonInviteServerTransaction.java 16 Jun 2009 07:54:41 -0000 1.10 +++ NonInviteServerTransaction.java 12 Aug 2009 10:34:24 -0000 @@ -219,6 +219,10 @@ _timerJ = _timerService.createTimer(this, 64 * T1, TimerJ); _response.setNeedSerialization(true); // optimization during timerJ + // Make sure dialog UOW is finished ASAP + if (getDialog() != null) { + getDialog().getDialogLifeCycle().onTransactionRemoved(getTransactionId(), false); // true or false? + } clearRequest(); } else { _state = TERMINATED; // TimerJ = 0 Index: Transaction.java =================================================================== RCS file: /cvs/sailfin/sip-stack/src/java/com/ericsson/ssa/sip/transaction/Transaction.java,v retrieving revision 1.18 diff -u -r1.18 Transaction.java — Transaction.java 28 Jul 2009 05:12:49 -0000 1.18 +++ Transaction.java 12 Aug 2009 10:34:24 -0000 @@ -102,7 +102,7 @@ static long T4 = _transactionManager.getTimerT4(); protected TransactionState _state; protected String _transactionId; private SipServletRequestImpl _request; + protected SipServletRequestImpl _request; protected boolean _reliableTransport = true; private long _transactionStartedTimestamp = 0; private long _lastAccessTimestamp = 0; BTW, the 503 response is not endless, there is a retry-after and the stream should stop after 32 seconds...
          Hide
          Scott Oaks added a comment -

          After discussion with Ericsson, we determined that it is easiest not to fix
          this. The clients will receive a 503 and can retry at a later point, and
          terminating the dialog earlier isn't really a viable option because of sip
          protocol issues.

          Under SSR, this will lead to a small number of failures (but within acceptable
          levels).

          Show
          Scott Oaks added a comment - After discussion with Ericsson, we determined that it is easiest not to fix this. The clients will receive a 503 and can retry at a later point, and terminating the dialog earlier isn't really a viable option because of sip protocol issues. Under SSR, this will lead to a small number of failures (but within acceptable levels).

            People

            • Assignee:
              sankara
              Reporter:
              Scott Oaks
            • Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: