Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-25465

States with signal handler scripts will cause crash during the item destruction if you switch between states enough.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.0.0
    • 4.8.1
    • None
    • Qt 4.8.1. Windows.
      It seems that Qt 5 have the same code in the relevant places.
      And the bug is not platform specific.

    Description

      The problem
      -----------
      
      The current ownership model selected for signal expressions attached to states
      did not account for certain cases.  A signal owns its current expression.  A
      state owns an expression that the signal had just before we entered this state.
      But when we enter a state an expression been set for a signal is the initial
      expression for this particular state, not an expression owned by this state.
      This would cause all kind of errors in a particularly complex case.  Here is an
      explanation of what happens under the old ownership model.
      
      
      QML:
          import QtQuick 1.0
      
          Rectangle {
              id: myRect
              width: 400
              height: 400
      
              states: [
                  State {
                      name: "state1"
                      PropertyChanges {
                          target: myRect
                          onHeightChanged: console.log("state1")
                          color: "green"
                      }
                  },
                  State {
                      name: "state2";
                      PropertyChanges {
                          target: myRect
                          onHeightChanged: console.log("state2")
                          color: "red"
                  }
              }]
          }
      
      
      Let's give our expressions ids:
        0x1 : console.log("state1")
        0x2 : console.log("state2")
      
      Initially:
           Rectangle.onHeightChanged: <no expression>
           Rectangle.state1
               expression: 0x1
               owns: <nothing>
           Rectangle.state2
               expression: 0x2
               owns: <nothing>
      
      Enter state1:
           Rectangle.onHeightChanged: 0x1
           Rectangle.state1
               expression: 0x1
               owns: <nothing>
           Rectangle.state2
               expression: 0x2
               owns: <nothing>
      
      Enter state2:
           Rectangle.onHeightChanged: 0x2
           Rectangle.state1
               expression: 0x1
               owns: <nothing>
           Rectangle.state2
               expression: 0x2
               owns: 0x1
      
      state2 now own expression that "conceptually" belongs to state1 and might
      still be set by state1.
      
      Enter state1:
           Rectangle.onHeightChanged: 0x1
           Rectangle.state1
               expression: 0x1
               owns: 0x2
           Rectangle.state2
               expression: 0x2
               owns: 0x1
      
      Now we have everything mixed up.  States owns each other's expression and in
      addition to that the rectangle's signal also owns one of the expression.  If
      we delete the rectangle the 0x1 expression would be deleted twice.
      
      Note that in addition to the crazy mix ups unless we enter a state at least
      once we would leak all the signal expressions for that state.  I am not sure
      how to check for leaks here.
      
      
      Short term solution (Patch attached)
      ---------------------------------
      
      Use reference counted pointers for the signal handler expressions.  Considering
      all the cases we want to preserve an expression:
      
        - State is destroyed but the item is alive and is in this state
        - State is destroyed but the item has a reverse action in its reverse
          list uses this expression (not sure it is actually usable)
        - The original item signal handler expression should be preserved
          regardless of the state we are in and regardless of what do we do
          with the states (add new, delete, change current state)
      
      It seems like reference counting is the only manageable solution unless
      the overall model is modified a little bit.
      
      
      General solution (Not implemented)
      ----------------------------------
      
      In the long run I would advise a more general refactoring with a strict
      rules of ownership for the expressions, state groups and states.  I
      would say that the reverse list should be moved into the state group and
      states should own their expressions.  And we do not allow destruction of
      the current state or any of the state's current state extends.
      
      When a state is destroyed we would delete all the expressions that
      belong to that state.  The reverse list should contain only references
      to the expressions that were the initial values of the item signal
      handlers.  Thus unless we are trying to remove current state (or a state
      that the current state extends) we should be fine from the semantic
      standpoint.
      

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            brasser Michael Brasser (closed Nokia identity) (Inactive)
            ibobyr Ilya Bobyr
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes