diff options
author | Neels Hofmeyr <neels@hofmeyr.de> | 2018-08-27 21:54:49 +0200 |
---|---|---|
committer | Neels Hofmeyr <neels@hofmeyr.de> | 2018-08-29 02:02:10 +0200 |
commit | 3ea8baeab00964217bd20027d6d61c625e62b5e4 (patch) | |
tree | 7bea0c9b17cd04f659e8455284e46c9d0bf9be7d /src | |
parent | d8b41fc677ad4a83a414d17215da2cd767cc47ad (diff) |
lchan_fsm: lchan_fail_to(): store target state early
lchan_fail_to() is a macro to preserve useful source file:line information in
logging. But a side effect is that its target state argument might evaluate
differently at the end of the macro, if, say, the fi->state has changed.
I hit such an instance on timeout of WAIT_RLL_RTP_ESTABLISH:
lchan_fsm_timer_cb() calls macro lchan_fail(), which calls
lchan_fail_to(lchan_fsm_on_error[fi->state]). Unlike for normal function
invocation, this argument changes as fi->state changes. Since releasing the
lchan_rtp_fsm already transitions the lchan fi into WAIT_RF_RELEASE_ACK, the
final state change of lchan_fail_to() suddenly evaluates to the broken state
instead of the intended WAIT_RF_RELEASE_ACK.
Early in lchan_fail_to(), store the argument's value as of macro invocation.
Change-Id: Id9bf4580a112ee5629f553a8bcb6b5b03b1c5f53
Diffstat (limited to 'src')
-rw-r--r-- | src/osmo-bsc/lchan_fsm.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/src/osmo-bsc/lchan_fsm.c b/src/osmo-bsc/lchan_fsm.c index 9c22bded4..e0015cbeb 100644 --- a/src/osmo-bsc/lchan_fsm.c +++ b/src/osmo-bsc/lchan_fsm.c @@ -211,9 +211,11 @@ struct state_timeout lchan_fsm_timeouts[32] = { /* Set a failure message, trigger the common actions to take on failure, transition to a state to * continue with (using state timeouts from lchan_fsm_timeouts[]). Assumes local variable fi exists. */ -#define lchan_fail_to(state_chg, fmt, args...) do { \ +#define lchan_fail_to(STATE_CHG, fmt, args...) do { \ struct gsm_lchan *_lchan = fi->priv; \ uint32_t state_was = fi->state; \ + /* Snapshot the target state, in case the macro argument evaluates differently later */ \ + const uint32_t state_chg = STATE_CHG; \ lchan_set_last_error(_lchan, "lchan %s in state %s: " fmt, \ _lchan->activate.concluded ? "failure" : "allocation failed", \ osmo_fsm_state_name(fi->fsm, state_was), ## args); \ |