summaryrefslogtreecommitdiffstats
path: root/tests/fsm
diff options
context:
space:
mode:
authorNeels Hofmeyr <neels@hofmeyr.de>2019-03-24 05:43:04 +0100
committerNeels Hofmeyr <nhofmeyr@sysmocom.de>2019-04-11 05:36:36 +0000
commitd28aa0c2f1fc8827ee7f6958ab8d13630b9d2be9 (patch)
tree9dd2fdb0f632ac212a6c97dc2aade58ef7e08f72 /tests/fsm
parent1f9cc018618e7d1e9a7a37e1ef08e059a4e02e87 (diff)
fsm_dealloc_test: no need for ST_DESTROYING
A separate ST_DESTROYING state originally helped with certain deallocation scenarios. But now that fsm.c avoids re-entering osmo_fsm_inst_term() twice and gracefully handles FSM instance deallocations for termination cascades, it is actually just as safe without a separate ST_DESTROYING state. ST_DESTROYING was used to flag deallocation and prevent entering osmo_fsm_inst_term() twice, which works only in a very limited range of scenarios. Remove ST_DESTROYING from fsm_dealloc_test.c to show that all tested scenarios still clean up gracefully. Change-Id: I05354e6cad9b82ba474fa50ffd41d481b3c697b4
Diffstat (limited to 'tests/fsm')
-rw-r--r--tests/fsm/fsm_dealloc_test.c54
-rw-r--r--tests/fsm/fsm_dealloc_test.err3265
2 files changed, 1520 insertions, 1799 deletions
diff --git a/tests/fsm/fsm_dealloc_test.c b/tests/fsm/fsm_dealloc_test.c
index f8d2b1ee..ce492056 100644
--- a/tests/fsm/fsm_dealloc_test.c
+++ b/tests/fsm/fsm_dealloc_test.c
@@ -22,7 +22,6 @@ static const struct value_string test_fsm_event_names[] = {
enum state {
ST_ALIVE,
- ST_DESTROYING,
};
enum objname {
@@ -148,52 +147,19 @@ void alive(struct osmo_fsm_inst *fi, uint32_t event, void *data)
case EV_OTHER_GONE:
if (other_gone(obj, data)) {
/* Something this object depends on is gone, trigger deallocation */
- osmo_fsm_inst_state_chg(fi, ST_DESTROYING, 0, 0);
+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, 0);
}
break;
case EV_CHILD_GONE:
if (!child_gone(obj, data)) {
/* All children are gone. Deallocate. */
- osmo_fsm_inst_state_chg(fi, ST_DESTROYING, 0, 0);
+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, 0);
}
break;
case EV_DESTROY:
- osmo_fsm_inst_state_chg(fi, ST_DESTROYING, 0, 0);
- break;
-
- default:
- OSMO_ASSERT(false);
- }
- PUT();
-}
-
-void destroying_onenter(struct osmo_fsm_inst *fi, uint32_t prev_state)
-{
- struct obj *obj = fi->priv;
- GET();
- LOGPFSML(fi, LOGL_DEBUG, "%s() from %s\n", __func__, osmo_fsm_state_name(fi->fsm, prev_state));
- osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, 0);
- PUT();
-}
-
-void destroying(struct osmo_fsm_inst *fi, uint32_t event, void *data)
-{
- struct obj *obj = fi->priv;
- GET();
- LOGPFSML(fi, LOGL_DEBUG, "%s(%s)\n", __func__, osmo_fsm_event_name(fi->fsm, event));
- switch (event) {
- case EV_OTHER_GONE:
- other_gone(obj, data);
- break;
-
- case EV_CHILD_GONE:
- child_gone(obj, data);
- break;
-
- case EV_DESTROY:
- LOGPFSML(fi, LOGL_DEBUG, "already destroying\n");
+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REGULAR, 0);
break;
default:
@@ -214,24 +180,10 @@ static const struct osmo_fsm_state test_fsm_states[] = {
,
.out_state_mask = 0
| S(ST_ALIVE)
- | S(ST_DESTROYING)
,
.onenter = alive_onenter,
.action = alive,
},
- [ST_DESTROYING] = {
- .name = "destroying",
- .in_event_mask = 0
- | S(EV_CHILD_GONE)
- | S(EV_OTHER_GONE)
- | S(EV_DESTROY)
- ,
- .out_state_mask = 0
- | S(ST_DESTROYING)
- ,
- .onenter = destroying_onenter,
- .action = destroying,
- },
};
void cleanup(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause)
diff --git a/tests/fsm/fsm_dealloc_test.err b/tests/fsm/fsm_dealloc_test.err
index aa7db51e..d12c5aa3 100644
--- a/tests/fsm/fsm_dealloc_test.err
+++ b/tests/fsm/fsm_dealloc_test.err
@@ -66,11 +66,7 @@ DLGLOBAL DEBUG test(root){alive}: alive(EV_OTHER_GONE)
DLGLOBAL DEBUG 3 (__twig1a.cleanup(),root.alive(),root.other_gone())
DLGLOBAL DEBUG test(root){alive}: EV_OTHER_GONE: Dropped reference root.other[0] = __twig1a
DLGLOBAL DEBUG 2 (__twig1a.cleanup(),root.alive())
-DLGLOBAL DEBUG test(root){alive}: state_chg to destroying
-DLGLOBAL DEBUG 3 (__twig1a.cleanup(),root.alive(),root.destroying_onenter())
-DLGLOBAL DEBUG test(root){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(root){destroying}: Ignoring trigger to terminate: already terminating
-DLGLOBAL DEBUG 2 (__twig1a.cleanup(),root.alive())
+DLGLOBAL DEBUG test(root){alive}: Ignoring trigger to terminate: already terminating
DLGLOBAL DEBUG 1 (__twig1a.cleanup())
DLGLOBAL DEBUG test(_branch1){alive}: Received Event EV_CHILD_GONE
DLGLOBAL DEBUG 2 (__twig1a.cleanup(),_branch1.alive())
@@ -79,131 +75,121 @@ DLGLOBAL DEBUG 3 (__twig1a.cleanup(),_branch1.alive(),_branch1.child_gone())
DLGLOBAL DEBUG test(_branch1){alive}: EV_CHILD_GONE: Dropped reference _branch1.child[0] = __twig1a
DLGLOBAL DEBUG test(_branch1){alive}: No more children
DLGLOBAL DEBUG 2 (__twig1a.cleanup(),_branch1.alive())
-DLGLOBAL DEBUG test(_branch1){alive}: state_chg to destroying
-DLGLOBAL DEBUG 3 (__twig1a.cleanup(),_branch1.alive(),_branch1.destroying_onenter())
-DLGLOBAL DEBUG test(_branch1){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(_branch1){destroying}: Ignoring trigger to terminate: already terminating
-DLGLOBAL DEBUG 2 (__twig1a.cleanup(),_branch1.alive())
+DLGLOBAL DEBUG test(_branch1){alive}: Ignoring trigger to terminate: already terminating
DLGLOBAL DEBUG 1 (__twig1a.cleanup())
DLGLOBAL DEBUG test(__twig1a){alive}: cleanup() done
DLGLOBAL DEBUG 0 (-)
DLGLOBAL DEBUG test(__twig1a){alive}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG test(_branch1){destroying}: Removing from parent test(root)
+DLGLOBAL DEBUG test(_branch1){alive}: Removing from parent test(root)
DLGLOBAL DEBUG 1 (_branch1.cleanup())
-DLGLOBAL DEBUG test(_branch1){destroying}: cleanup()
-DLGLOBAL DEBUG test(_branch1){destroying}: scene forgets _branch1
-DLGLOBAL DEBUG test(_branch1){destroying}: removing reference _branch1.other[0] -> other
+DLGLOBAL DEBUG test(_branch1){alive}: cleanup()
+DLGLOBAL DEBUG test(_branch1){alive}: scene forgets _branch1
+DLGLOBAL DEBUG test(_branch1){alive}: removing reference _branch1.other[0] -> other
DLGLOBAL DEBUG test(other){alive}: Received Event EV_OTHER_GONE
DLGLOBAL DEBUG 2 (_branch1.cleanup(),other.alive())
DLGLOBAL DEBUG test(other){alive}: alive(EV_OTHER_GONE)
DLGLOBAL DEBUG 3 (_branch1.cleanup(),other.alive(),other.other_gone())
DLGLOBAL DEBUG test(other){alive}: EV_OTHER_GONE: Dropped reference other.other[1] = _branch1
DLGLOBAL DEBUG 2 (_branch1.cleanup(),other.alive())
-DLGLOBAL DEBUG test(other){alive}: state_chg to destroying
-DLGLOBAL DEBUG 3 (_branch1.cleanup(),other.alive(),other.destroying_onenter())
-DLGLOBAL DEBUG test(other){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(other){destroying}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
-DLGLOBAL DEBUG test(other){destroying}: pre_term()
-DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup())
-DLGLOBAL DEBUG test(other){destroying}: cleanup()
-DLGLOBAL DEBUG test(other){destroying}: scene forgets other
-DLGLOBAL DEBUG test(other){destroying}: removing reference other.other[0] -> _branch0
+DLGLOBAL DEBUG test(other){alive}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
+DLGLOBAL DEBUG test(other){alive}: pre_term()
+DLGLOBAL DEBUG 3 (_branch1.cleanup(),other.alive(),other.cleanup())
+DLGLOBAL DEBUG test(other){alive}: cleanup()
+DLGLOBAL DEBUG test(other){alive}: scene forgets other
+DLGLOBAL DEBUG test(other){alive}: removing reference other.other[0] -> _branch0
DLGLOBAL DEBUG test(_branch0){alive}: Received Event EV_OTHER_GONE
-DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
DLGLOBAL DEBUG test(_branch0){alive}: alive(EV_OTHER_GONE)
-DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.other_gone())
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.other_gone())
DLGLOBAL DEBUG test(_branch0){alive}: EV_OTHER_GONE: Dropped reference _branch0.other[0] = other
-DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive())
-DLGLOBAL DEBUG test(_branch0){alive}: state_chg to destroying
-DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter())
-DLGLOBAL DEBUG test(_branch0){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(_branch0){destroying}: Terminating in cascade, depth 4 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
-DLGLOBAL DEBUG test(_branch0){destroying}: pre_term()
+DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(_branch0){alive}: Terminating in cascade, depth 4 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
+DLGLOBAL DEBUG test(_branch0){alive}: pre_term()
DLGLOBAL DEBUG test(__twig0b){alive}: Terminating in cascade, depth 5 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(__twig0b){alive}: pre_term()
DLGLOBAL DEBUG test(__twig0b){alive}: Removing from parent test(_branch0)
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0b.cleanup())
DLGLOBAL DEBUG test(__twig0b){alive}: cleanup()
DLGLOBAL DEBUG test(__twig0b){alive}: scene forgets __twig0b
-DLGLOBAL DEBUG test(_branch0){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 9 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: EV_CHILD_GONE: Dropped reference _branch0.child[1] = __twig0b
-DLGLOBAL DEBUG test(_branch0){destroying}: still exists: child[0]
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
+DLGLOBAL DEBUG test(_branch0){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0b.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0b.cleanup(),_branch0.child_gone())
+DLGLOBAL DEBUG test(_branch0){alive}: EV_CHILD_GONE: Dropped reference _branch0.child[1] = __twig0b
+DLGLOBAL DEBUG test(_branch0){alive}: still exists: child[0]
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0b.cleanup())
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0b.cleanup())
DLGLOBAL DEBUG test(__twig0b){alive}: cleanup() done
-DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter())
+DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
DLGLOBAL DEBUG test(__twig0b){alive}: Deferring: will deallocate with test(root)
DLGLOBAL DEBUG test(__twig0a){alive}: Terminating in cascade, depth 5 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(__twig0a){alive}: pre_term()
DLGLOBAL DEBUG test(__twig0a){alive}: Removing from parent test(_branch0)
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
DLGLOBAL DEBUG test(__twig0a){alive}: cleanup()
DLGLOBAL DEBUG test(__twig0a){alive}: scene forgets __twig0a
DLGLOBAL DEBUG test(__twig0a){alive}: removing reference __twig0a.other[0] -> other
-DLGLOBAL DEBUG test(other){destroying}: Received Event EV_OTHER_GONE
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(other){destroying}: destroying(EV_OTHER_GONE)
-DLGLOBAL DEBUG 9 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 9 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: EV_CHILD_GONE: Dropped reference _branch0.child[0] = __twig0a
-DLGLOBAL DEBUG test(_branch0){destroying}: No more children
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
+DLGLOBAL DEBUG test(other){alive}: Received Event EV_OTHER_GONE
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),2*other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(other){alive}: alive(EV_OTHER_GONE)
+DLGLOBAL DEBUG 7 (_branch1.cleanup(),2*other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup(),other.other_gone())
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),2*other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0a.cleanup(),_branch0.child_gone())
+DLGLOBAL DEBUG test(_branch0){alive}: EV_CHILD_GONE: Dropped reference _branch0.child[0] = __twig0a
+DLGLOBAL DEBUG test(_branch0){alive}: No more children
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: Ignoring trigger to terminate: already terminating
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
DLGLOBAL DEBUG test(__twig0a){alive}: cleanup() done
-DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter())
+DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
DLGLOBAL DEBUG test(__twig0a){alive}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG test(_branch0){destroying}: Removing from parent test(root)
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: cleanup()
-DLGLOBAL DEBUG test(_branch0){destroying}: scene forgets _branch0
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 9 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(root){destroying}: EV_CHILD_GONE: Dropped reference root.child[0] = _branch0
-DLGLOBAL DEBUG test(root){destroying}: still exists: child[1]
-DLGLOBAL DEBUG 8 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),_
-DLGLOBAL DEBUG test(_branch0){destroying}: cleanup() done
-DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter())
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter(),r
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG test(root){destroying}: EV_CHILD_GONE with NULL data, must be a parent_term event. Ignore.
-DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive(),_branch0.destroying_onenter())
-DLGLOBAL DEBUG test(_branch0){destroying}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.alive())
-DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup())
-DLGLOBAL DEBUG test(other){destroying}: cleanup() done
-DLGLOBAL DEBUG 3 (_branch1.cleanup(),other.alive(),other.destroying_onenter())
-DLGLOBAL DEBUG test(other){destroying}: Deferring: will deallocate with test(root)
+DLGLOBAL DEBUG test(_branch0){alive}: Removing from parent test(root)
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: cleanup()
+DLGLOBAL DEBUG test(_branch0){alive}: scene forgets _branch0
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup(),root.alive())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 7 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup(),root.alive(),root.child_gone())
+DLGLOBAL DEBUG test(root){alive}: EV_CHILD_GONE: Dropped reference root.child[0] = _branch0
+DLGLOBAL DEBUG test(root){alive}: still exists: child[1]
+DLGLOBAL DEBUG 6 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup(),root.alive())
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: cleanup() done
+DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 5 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),root.alive())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG test(root){alive}: EV_CHILD_GONE with NULL data, must be a parent_term event. Ignore.
+DLGLOBAL DEBUG 4 (_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(_branch0){alive}: Deferring: will deallocate with test(root)
+DLGLOBAL DEBUG 3 (_branch1.cleanup(),other.alive(),other.cleanup())
+DLGLOBAL DEBUG test(other){alive}: cleanup() done
DLGLOBAL DEBUG 2 (_branch1.cleanup(),other.alive())
+DLGLOBAL DEBUG test(other){alive}: Deferring: will deallocate with test(root)
DLGLOBAL DEBUG 1 (_branch1.cleanup())
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 2 (_branch1.cleanup(),root.destroying())
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 3 (_branch1.cleanup(),root.destroying(),root.child_gone())
-DLGLOBAL DEBUG test(root){destroying}: EV_CHILD_GONE: Dropped reference root.child[1] = _branch1
-DLGLOBAL DEBUG test(root){destroying}: No more children
-DLGLOBAL DEBUG 2 (_branch1.cleanup(),root.destroying())
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 2 (_branch1.cleanup(),root.alive())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 3 (_branch1.cleanup(),root.alive(),root.child_gone())
+DLGLOBAL DEBUG test(root){alive}: EV_CHILD_GONE: Dropped reference root.child[1] = _branch1
+DLGLOBAL DEBUG test(root){alive}: No more children
+DLGLOBAL DEBUG 2 (_branch1.cleanup(),root.alive())
+DLGLOBAL DEBUG test(root){alive}: Ignoring trigger to terminate: already terminating
DLGLOBAL DEBUG 1 (_branch1.cleanup())
-DLGLOBAL DEBUG test(_branch1){destroying}: cleanup() done
+DLGLOBAL DEBUG test(_branch1){alive}: cleanup() done
DLGLOBAL DEBUG 0 (-)
-DLGLOBAL DEBUG test(_branch1){destroying}: Deferring: will deallocate with test(root)
+DLGLOBAL DEBUG test(_branch1){alive}: Deferring: will deallocate with test(root)
DLGLOBAL DEBUG 1 (root.cleanup())
-DLGLOBAL DEBUG test(root){destroying}: cleanup()
-DLGLOBAL DEBUG test(root){destroying}: scene forgets root
-DLGLOBAL DEBUG test(root){destroying}: cleanup() done
+DLGLOBAL DEBUG test(root){alive}: cleanup()
+DLGLOBAL DEBUG test(root){alive}: scene forgets root
+DLGLOBAL DEBUG test(root){alive}: cleanup() done
DLGLOBAL DEBUG 0 (-)
-DLGLOBAL DEBUG test(root){destroying}: Deallocated, including all deferred deallocations
+DLGLOBAL DEBUG test(root){alive}: Deallocated, including all deferred deallocations
DLGLOBAL DEBUG --- after term cascade:
DLGLOBAL DEBUG --- all deallocated.
DLGLOBAL DEBUG scene_alloc()
@@ -243,177 +229,164 @@ DLGLOBAL DEBUG --- destroy-event at root
DLGLOBAL DEBUG test(root){alive}: Received Event EV_DESTROY
DLGLOBAL DEBUG 1 (root.alive())
DLGLOBAL DEBUG test(root){alive}: alive(EV_DESTROY)
-DLGLOBAL DEBUG test(root){alive}: state_chg to destroying
-DLGLOBAL DEBUG 2 (root.alive(),root.destroying_onenter())
-DLGLOBAL DEBUG test(root){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(root){destroying}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
-DLGLOBAL DEBUG test(root){destroying}: pre_term()
+DLGLOBAL DEBUG test(root){alive}: Terminating (cause = OSMO_FSM_TERM_REGULAR)
+DLGLOBAL DEBUG test(root){alive}: pre_term()
DLGLOBAL DEBUG test(_branch1){alive}: Terminating in cascade, depth 2 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(_branch1){alive}: pre_term()
DLGLOBAL DEBUG test(__twig1b){alive}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(__twig1b){alive}: pre_term()
DLGLOBAL DEBUG test(__twig1b){alive}: Removing from parent test(_branch1)
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),__twig1b.cleanup())
+DLGLOBAL DEBUG 2 (root.alive(),__twig1b.cleanup())
DLGLOBAL DEBUG test(__twig1b){alive}: cleanup()
DLGLOBAL DEBUG test(__twig1b){alive}: scene forgets __twig1b
DLGLOBAL DEBUG test(_branch1){alive}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1b.cleanup(),_branch1.alive())
+DLGLOBAL DEBUG 3 (root.alive(),__twig1b.cleanup(),_branch1.alive())
DLGLOBAL DEBUG test(_branch1){alive}: alive(EV_CHILD_GONE)
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),__twig1b.cleanup(),_branch1.alive(),_branch1.child_gone())
+DLGLOBAL DEBUG 4 (root.alive(),__twig1b.cleanup(),_branch1.alive(),_branch1.child_gone())
DLGLOBAL DEBUG test(_branch1){alive}: EV_CHILD_GONE: Dropped reference _branch1.child[1] = __twig1b
DLGLOBAL DEBUG test(_branch1){alive}: still exists: child[0]
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1b.cleanup(),_branch1.alive())
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),__twig1b.cleanup())
+DLGLOBAL DEBUG 3 (root.alive(),__twig1b.cleanup(),_branch1.alive())
+DLGLOBAL DEBUG 2 (root.alive(),__twig1b.cleanup())
DLGLOBAL DEBUG test(__twig1b){alive}: cleanup() done
-DLGLOBAL DEBUG 2 (root.alive(),root.destroying_onenter())
+DLGLOBAL DEBUG 1 (root.alive())
DLGLOBAL DEBUG test(__twig1b){alive}: Deferring: will deallocate with test(root)
DLGLOBAL DEBUG test(__twig1a){alive}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(__twig1a){alive}: pre_term()
DLGLOBAL DEBUG test(__twig1a){alive}: Removing from parent test(_branch1)
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),__twig1a.cleanup())
+DLGLOBAL DEBUG 2 (root.alive(),__twig1a.cleanup())
DLGLOBAL DEBUG test(__twig1a){alive}: cleanup()
DLGLOBAL DEBUG test(__twig1a){alive}: scene forgets __twig1a
DLGLOBAL DEBUG test(__twig1a){alive}: removing reference __twig1a.other[0] -> root
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_OTHER_GONE
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),root.destroying())
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_OTHER_GONE)
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),root.destroying(),root.other_gone())
-DLGLOBAL DEBUG test(root){destroying}: EV_OTHER_GONE: Dropped reference root.other[0] = __twig1a
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),root.destroying())
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),__twig1a.cleanup())
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_OTHER_GONE
+DLGLOBAL DEBUG 3 (2*root.alive(),__twig1a.cleanup())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_OTHER_GONE)
+DLGLOBAL DEBUG 4 (2*root.alive(),__twig1a.cleanup(),root.other_gone())
+DLGLOBAL DEBUG test(root){alive}: EV_OTHER_GONE: Dropped reference root.other[0] = __twig1a
+DLGLOBAL DEBUG 3 (2*root.alive(),__twig1a.cleanup())
+DLGLOBAL DEBUG test(root){alive}: Ignoring trigger to terminate: already terminating
+DLGLOBAL DEBUG 2 (root.alive(),__twig1a.cleanup())
DLGLOBAL DEBUG test(_branch1){alive}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),_branch1.alive())
+DLGLOBAL DEBUG 3 (root.alive(),__twig1a.cleanup(),_branch1.alive())
DLGLOBAL DEBUG test(_branch1){alive}: alive(EV_CHILD_GONE)
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),_branch1.alive(),_branch1.child_gone())
+DLGLOBAL DEBUG 4 (root.alive(),__twig1a.cleanup(),_branch1.alive(),_branch1.child_gone())
DLGLOBAL DEBUG test(_branch1){alive}: EV_CHILD_GONE: Dropped reference _branch1.child[0] = __twig1a
DLGLOBAL DEBUG test(_branch1){alive}: No more children
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),_branch1.alive())
-DLGLOBAL DEBUG test(_branch1){alive}: state_chg to destroying
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),_branch1.alive(),_branch1.destroying_onenter())
-DLGLOBAL DEBUG test(_branch1){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(_branch1){destroying}: Ignoring trigger to terminate: already terminating
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),__twig1a.cleanup(),_branch1.alive())
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),__twig1a.cleanup())
+DLGLOBAL DEBUG 3 (root.alive(),__twig1a.cleanup(),_branch1.alive())
+DLGLOBAL DEBUG test(_branch1){alive}: Ignoring trigger to terminate: already terminating
+DLGLOBAL DEBUG 2 (root.alive(),__twig1a.cleanup())
DLGLOBAL DEBUG test(__twig1a){alive}: cleanup() done
-DLGLOBAL DEBUG 2 (root.alive(),root.destroying_onenter())
+DLGLOBAL DEBUG 1 (root.alive())
DLGLOBAL DEBUG test(__twig1a){alive}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG test(_branch1){destroying}: Removing from parent test(root)
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),_branch1.cleanup())
-DLGLOBAL DEBUG test(_branch1){destroying}: cleanup()
-DLGLOBAL DEBUG test(_branch1){destroying}: scene forgets _branch1
-DLGLOBAL DEBUG test(_branch1){destroying}: removing reference _branch1.other[0] -> other
+DLGLOBAL DEBUG test(_branch1){alive}: Removing from parent test(root)
+DLGLOBAL DEBUG 2 (root.alive(),_branch1.cleanup())
+DLGLOBAL DEBUG test(_branch1){alive}: cleanup()
+DLGLOBAL DEBUG test(_branch1){alive}: scene forgets _branch1
+DLGLOBAL DEBUG test(_branch1){alive}: removing reference _branch1.other[0] -> other
DLGLOBAL DEBUG test(other){alive}: Received Event EV_OTHER_GONE
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive())
+DLGLOBAL DEBUG 3 (root.alive(),_branch1.cleanup(),other.alive())
DLGLOBAL DEBUG test(other){alive}: alive(EV_OTHER_GONE)
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.other_gone())
+DLGLOBAL DEBUG 4 (root.alive(),_branch1.cleanup(),other.alive(),other.other_gone())
DLGLOBAL DEBUG test(other){alive}: EV_OTHER_GONE: Dropped reference other.other[1] = _branch1
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive())
-DLGLOBAL DEBUG test(other){alive}: state_chg to destroying
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter())
-DLGLOBAL DEBUG test(other){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(other){destroying}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
-DLGLOBAL DEBUG test(other){destroying}: pre_term()
-DLGLOBAL DEBUG 6 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup())
-DLGLOBAL DEBUG test(other){destroying}: cleanup()
-DLGLOBAL DEBUG test(other){destroying}: scene forgets other
-DLGLOBAL DEBUG test(other){destroying}: removing reference other.other[0] -> _branch0
+DLGLOBAL DEBUG 3 (root.alive(),_branch1.cleanup(),other.alive())
+DLGLOBAL DEBUG test(other){alive}: Terminating in cascade, depth 3 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
+DLGLOBAL DEBUG test(other){alive}: pre_term()
+DLGLOBAL DEBUG 4 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup())
+DLGLOBAL DEBUG test(other){alive}: cleanup()
+DLGLOBAL DEBUG test(other){alive}: scene forgets other
+DLGLOBAL DEBUG test(other){alive}: removing reference other.other[0] -> _branch0
DLGLOBAL DEBUG test(_branch0){alive}: Received Event EV_OTHER_GONE
-DLGLOBAL DEBUG 7 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG 5 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
DLGLOBAL DEBUG test(_branch0){alive}: alive(EV_OTHER_GONE)
-DLGLOBAL DEBUG 8 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.other_gone())
DLGLOBAL DEBUG test(_branch0){alive}: EV_OTHER_GONE: Dropped reference _branch0.other[0] = other
-DLGLOBAL DEBUG 7 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(_branch0){alive}: state_chg to destroying
-DLGLOBAL DEBUG 8 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(_branch0){destroying}: destroying_onenter() from alive
-DLGLOBAL DEBUG test(_branch0){destroying}: Terminating in cascade, depth 4 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
-DLGLOBAL DEBUG test(_branch0){destroying}: pre_term()
+DLGLOBAL DEBUG 5 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(_branch0){alive}: Terminating in cascade, depth 4 (cause = OSMO_FSM_TERM_REGULAR, caused by: test(root))
+DLGLOBAL DEBUG test(_branch0){alive}: pre_term()
DLGLOBAL DEBUG test(__twig0b){alive}: Terminating in cascade, depth 5 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(__twig0b){alive}: pre_term()
DLGLOBAL DEBUG test(__twig0b){alive}: Removing from parent test(_branch0)
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0b.cleanup())
DLGLOBAL DEBUG test(__twig0b){alive}: cleanup()
DLGLOBAL DEBUG test(__twig0b){alive}: scene forgets __twig0b
-DLGLOBAL DEBUG test(_branch0){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(_branch0){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 11 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(_branch0){destroying}: EV_CHILD_GONE: Dropped reference _branch0.child[1] = __twig0b
-DLGLOBAL DEBUG test(_branch0){destroying}: still exists: child[0]
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG test(_branch0){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 7 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0b.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 8 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0b.cleanup(),_branch0.child_gone())
+DLGLOBAL DEBUG test(_branch0){alive}: EV_CHILD_GONE: Dropped reference _branch0.child[1] = __twig0b
+DLGLOBAL DEBUG test(_branch0){alive}: still exists: child[0]
+DLGLOBAL DEBUG 7 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0b.cleanup())
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0b.cleanup())
DLGLOBAL DEBUG test(__twig0b){alive}: cleanup() done
-DLGLOBAL DEBUG 8 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG 5 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
DLGLOBAL DEBUG test(__twig0b){alive}: Deferring: will deallocate with test(root)
DLGLOBAL DEBUG test(__twig0a){alive}: Terminating in cascade, depth 5 (cause = OSMO_FSM_TERM_PARENT, caused by: test(root))
DLGLOBAL DEBUG test(__twig0a){alive}: pre_term()
DLGLOBAL DEBUG test(__twig0a){alive}: Removing from parent test(_branch0)
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
DLGLOBAL DEBUG test(__twig0a){alive}: cleanup()
DLGLOBAL DEBUG test(__twig0a){alive}: scene forgets __twig0a
DLGLOBAL DEBUG test(__twig0a){alive}: removing reference __twig0a.other[0] -> other
-DLGLOBAL DEBUG test(other){destroying}: Received Event EV_OTHER_GONE
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(other){destroying}: destroying(EV_OTHER_GONE)
-DLGLOBAL DEBUG 11 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(_branch0){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(_branch0){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 11 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(_branch0){destroying}: EV_CHILD_GONE: Dropped reference _branch0.child[0] = __twig0a
-DLGLOBAL DEBUG test(_branch0){destroying}: No more children
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG test(other){alive}: Received Event EV_OTHER_GONE
+DLGLOBAL DEBUG 7 (root.alive(),_branch1.cleanup(),2*other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(other){alive}: alive(EV_OTHER_GONE)
+DLGLOBAL DEBUG 8 (root.alive(),_branch1.cleanup(),2*other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup(),other.other_gone())
+DLGLOBAL DEBUG 7 (root.alive(),_branch1.cleanup(),2*other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 7 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 8 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0a.cleanup(),_branch0.child_gone())
+DLGLOBAL DEBUG test(_branch0){alive}: EV_CHILD_GONE: Dropped reference _branch0.child[0] = __twig0a
+DLGLOBAL DEBUG test(_branch0){alive}: No more children
+DLGLOBAL DEBUG 7 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),2*_branch0.alive(),__twig0a.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: Ignoring trigger to terminate: already terminating
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),__twig0a.cleanup())
DLGLOBAL DEBUG test(__twig0a){alive}: cleanup() done
-DLGLOBAL DEBUG 8 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
+DLGLOBAL DEBUG 5 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
DLGLOBAL DEBUG test(__twig0a){alive}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG test(_branch0){destroying}: Removing from parent test(root)
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(_branch0){destroying}: cleanup()
-DLGLOBAL DEBUG test(_branch0){destroying}: scene forgets _branch0
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 11 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG test(root){destroying}: EV_CHILD_GONE: Dropped reference root.child[0] = _branch0
-DLGLOBAL DEBUG test(root){destroying}: still exists: child[1]
-DLGLOBAL DEBUG 10 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(_branch0){destroying}: cleanup() done
-DLGLOBAL DEBUG 8 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 9 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG test(root){destroying}: EV_CHILD_GONE with NULL data, must be a parent_term event. Ignore.
-DLGLOBAL DEBUG 8 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG test(_branch0){destroying}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG 7 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup(),_branch0.
-DLGLOBAL DEBUG 6 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter(),other.cleanup())
-DLGLOBAL DEBUG test(other){destroying}: cleanup() done
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive(),other.destroying_onenter())
-DLGLOBAL DEBUG test(other){destroying}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),other.alive())
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),_branch1.cleanup())
-DLGLOBAL DEBUG test(root){destroying}: Received Event EV_CHILD_GONE
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),root.destroying())
-DLGLOBAL DEBUG test(root){destroying}: destroying(EV_CHILD_GONE)
-DLGLOBAL DEBUG 5 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),root.destroying(),root.child_gone())
-DLGLOBAL DEBUG test(root){destroying}: EV_CHILD_GONE: Dropped reference root.child[1] = _branch1
-DLGLOBAL DEBUG test(root){destroying}: No more children
-DLGLOBAL DEBUG 4 (root.alive(),root.destroying_onenter(),_branch1.cleanup(),root.destroying())
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),_branch1.cleanup())
-DLGLOBAL DEBUG test(_branch1){destroying}: cleanup() done
-DLGLOBAL DEBUG 2 (root.alive(),root.destroying_onenter())
-DLGLOBAL DEBUG test(_branch1){destroying}: Deferring: will deallocate with test(root)
-DLGLOBAL DEBUG 3 (root.alive(),root.destroying_onenter(),root.cleanup())
-DLGLOBAL DEBUG test(root){destroying}: cleanup()
-DLGLOBAL DEBUG test(root){destroying}: scene forgets root
-DLGLOBAL DEBUG test(root){destroying}: cleanup() done
-DLGLOBAL DEBUG 2 (root.alive(),root.destroying_onenter())
-DLGLOBAL DEBUG test(root){destroying}: Deallocated, including all deferred deallocations
+DLGLOBAL DEBUG test(_branch0){alive}: Removing from parent test(root)
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: cleanup()
+DLGLOBAL DEBUG test(_branch0){alive}: scene forgets _branch0
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 7 (2*root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 8 (2*root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup(),root.child_gone())
+DLGLOBAL DEBUG test(root){alive}: EV_CHILD_GONE: Dropped reference root.child[0] = _branch0
+DLGLOBAL DEBUG test(root){alive}: still exists: child[1]
+DLGLOBAL DEBUG 7 (2*root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup())
+DLGLOBAL DEBUG 6 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive(),_branch0.cleanup())
+DLGLOBAL DEBUG test(_branch0){alive}: cleanup() done
+DLGLOBAL DEBUG 5 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 6 (2*root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG test(root){alive}: EV_CHILD_GONE with NULL data, must be a parent_term event. Ignore.
+DLGLOBAL DEBUG 5 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup(),_branch0.alive())
+DLGLOBAL DEBUG test(_branch0){alive}: Deferring: will deallocate with test(root)
+DLGLOBAL DEBUG 4 (root.alive(),_branch1.cleanup(),other.alive(),other.cleanup())
+DLGLOBAL DEBUG test(other){alive}: cleanup() done
+DLGLOBAL DEBUG 3 (root.alive(),_branch1.cleanup(),other.alive())
+DLGLOBAL DEBUG test(other){alive}: Deferring: will deallocate with test(root)
+DLGLOBAL DEBUG 2 (root.alive(),_branch1.cleanup())
+DLGLOBAL DEBUG test(root){alive}: Received Event EV_CHILD_GONE
+DLGLOBAL DEBUG 3 (2*root.alive(),_branch1.cleanup())
+DLGLOBAL DEBUG test(root){alive}: alive(EV_CHILD_GONE)
+DLGLOBAL DEBUG 4 (2*root.alive(),_branch1.cleanup(),root.child_gone())
+DLGLOBAL DEBUG test(root){alive}: EV_CHILD_GONE: Dropped reference root.child[1] = _branch1
+DLGLOBAL DEBUG test(root){alive}: No more children