Details
-
Bug
-
Resolution: Done
-
P3: Somewhat important
-
4.8.1
-
None
-
c4cef6fae9f2a55f21fc9517855dfcf659c89081
Description
Let's have following state machine ('@' marks initial states of each compound state):
+---------------------------------------+ | s2 (parallel) | +---------------------------------------+ | | | +-------------------------+ | | | s21 | | | +-------------------------+ | | | | | | | +----+ +----+ | | --------->|s211| @---->|s212| | | / | | +----+ +----+ | | / | | | | / | +-------------------------+ | +----+ t1 / | | @---->| s1 |-----+ | +------------------------+ | +----+ \ | | s22 | | \ | +------------------------+ | \ | | | | \ | | +----+ +----+ | | ---------------->|s221| @---->|s222| | | | | +----+ +----+ | | | | | | | +------------------------+ | | | +---------------------------------------+
See multitarget.cpp for implementation.
Running the example program outputs:
virtual void MyState::onEntry(QEvent*): s1 virtual void MyState::onExit(QEvent*): s1 virtual void NullTransition::onTransition(QEvent*): t virtual void MyState::onEntry(QEvent*): s2 virtual void MyState::onEntry(QEvent*): s211 virtual void MyState::onEntry(QEvent*): s22 virtual void MyState::onEntry(QEvent*): s21 virtual void MyState::onEntry(QEvent*): s222 virtual void MyState::onEntry(QEvent*): s221
So it can be seen that after transition t1 is invoked, both s221 and s222 are entered, but it should never happen that two children inside a compound state are active at the same time. One would expect that t1 will make active only s2, s21, s211, s22 and s221.
Apparently, the QStateMachine implementation first selects s211 for activation. Then it selects all its ancestors, making s21 and s2 active. If finds out that s2 is a parallel state group, so it activates all its children that are not yet active, in the example s22. Because s22 is a compound state, state machine activates also its initial state s222 - it's not aware that there is s221 going to be activated, right after s1-s211 component of transition t1 is processed. So finally, we will end up with both s211 and s222 active.
The state machine should ensure that compound state's initial state is entered only when there isn't any of its siblings being activated by a multi target transition.
Workaround
Seems that there is a possible workaround for this bug, see multitarget-workaround.cpp. When transition is invoked, it temporarily replaces the target's parent initial state with the target state itself. This prevents the initial state from being wrongly selected. When onEntry method of target is called, it restores the original initial state.
Attachments
For Gerrit Dashboard: QTBUG-25958 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
30678,1 | statemachine: Fix state entry bug for parallel state groups | master | qt/qtbase | Status: MERGED | +2 | 0 |
89775,7 | Undo: Fix state entry bug for parallel state groups | 5.3 | qt/qtbase | Status: MERGED | +2 | 0 |