Details
-
Bug
-
Resolution: Done
-
P2: Important
-
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.