<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/9389">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add osmo_fsm_inst_state_chg_keep_timer()<br><br>Change-Id: I3c0e53b846b2208bd201ace99777f2286ea39ae8<br>---<br>M include/osmocom/core/fsm.h<br>M src/fsm.c<br>M tests/fsm/fsm_test.c<br>M tests/fsm/fsm_test.err<br>4 files changed, 188 insertions(+), 35 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h</span><br><span>index 174396a..67e00ad 100644</span><br><span>--- a/include/osmocom/core/fsm.h</span><br><span>+++ b/include/osmocom/core/fsm.h</span><br><span>@@ -182,6 +182,21 @@</span><br><span>                              unsigned long timeout_secs, int T,</span><br><span>                           const char *file, int line);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! perform a state change while keeping the current timer running.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This is useful to keep a timeout across several states (without having to round the</span><br><span style="color: hsl(120, 100%, 40%);">+ *  remaining time to seconds).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This is a macro that calls _osmo_fsm_inst_state_chg_keep_timer() with the given</span><br><span style="color: hsl(120, 100%, 40%);">+ *  parameters as well as the caller's source file and line number for logging</span><br><span style="color: hsl(120, 100%, 40%);">+ *  purposes. See there for documentation.</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+#define osmo_fsm_inst_state_chg_keep_timer(fi, new_state) \</span><br><span style="color: hsl(120, 100%, 40%);">+   _osmo_fsm_inst_state_chg_keep_timer(fi, new_state, \</span><br><span style="color: hsl(120, 100%, 40%);">+                           __BASE_FILE__, __LINE__)</span><br><span style="color: hsl(120, 100%, 40%);">+int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state,</span><br><span style="color: hsl(120, 100%, 40%);">+                                      const char *file, int line);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! dispatch an event to an osmocom finite state machine instance</span><br><span>  *</span><br><span>  *  This is a macro that calls _osmo_fsm_inst_dispatch() with the given</span><br><span>diff --git a/src/fsm.c b/src/fsm.c</span><br><span>index 0370f65..b5af2e7 100644</span><br><span>--- a/src/fsm.c</span><br><span>+++ b/src/fsm.c</span><br><span>@@ -429,15 +429,56 @@</span><br><span>                return fsm->states[state].name;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int state_chg(struct osmo_fsm_inst *fi, uint32_t new_state,</span><br><span style="color: hsl(120, 100%, 40%);">+                    bool keep_timer, unsigned long timeout_secs, int T,</span><br><span style="color: hsl(120, 100%, 40%);">+                   const char *file, int line)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct osmo_fsm *fsm = fi->fsm;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t old_state = fi->state;</span><br><span style="color: hsl(120, 100%, 40%);">+    const struct osmo_fsm_state *st = &fsm->states[fi->state];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* validate if new_state is a valid state */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!(st->out_state_mask & (1 << new_state))) {</span><br><span style="color: hsl(120, 100%, 40%);">+          LOGPFSMLSRC(fi, LOGL_ERROR, file, line,</span><br><span style="color: hsl(120, 100%, 40%);">+                           "transition to state %s not permitted!\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                          osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(120, 100%, 40%);">+             return -EPERM;</span><br><span style="color: hsl(120, 100%, 40%);">+        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!keep_timer) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* delete the old timer */</span><br><span style="color: hsl(120, 100%, 40%);">+            osmo_timer_del(&fi->timer);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (st->onleave)</span><br><span style="color: hsl(120, 100%, 40%);">+           st->onleave(fi, new_state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      LOGPFSMSRC(fi, file, line, "state_chg to %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(120, 100%, 40%);">+      fi->state = new_state;</span><br><span style="color: hsl(120, 100%, 40%);">+     st = &fsm->states[new_state];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        if (!keep_timer && timeout_secs) {</span><br><span style="color: hsl(120, 100%, 40%);">+            fi->T = T;</span><br><span style="color: hsl(120, 100%, 40%);">+         osmo_timer_schedule(&fi->timer, timeout_secs, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Call 'onenter' last, user might terminate FSM from there */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (st->onenter)</span><br><span style="color: hsl(120, 100%, 40%);">+           st->onenter(fi, old_state);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! perform a state change of the given FSM instance</span><br><span>  *</span><br><span>  *  Best invoke via the osmo_fsm_inst_state_chg() macro which logs the source</span><br><span>  *  file where the state change was effected. Alternatively, you may pass \a</span><br><span>  *  file as NULL to use the normal file/line indication instead.</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- *  All changes to the FSM instance state must be made via this</span><br><span style="color: hsl(120, 100%, 40%);">+ *  All changes to the FSM instance state must be made via an osmo_fsm_inst_state_chg_*</span><br><span>  *  function.  It verifies that the existing state actually permits a</span><br><span style="color: hsl(0, 100%, 40%);">- *  transiiton to new_state.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  transition to new_state.</span><br><span>  *</span><br><span>  *  timeout_secs and T are optional parameters, and only have any effect</span><br><span>  *  if timeout_secs is not 0.  If the timeout function is used, then the</span><br><span>@@ -457,39 +498,32 @@</span><br><span>                          unsigned long timeout_secs, int T,</span><br><span>                           const char *file, int line)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-   struct osmo_fsm *fsm = fi->fsm;</span><br><span style="color: hsl(0, 100%, 40%);">-      uint32_t old_state = fi->state;</span><br><span style="color: hsl(0, 100%, 40%);">-      const struct osmo_fsm_state *st = &fsm->states[fi->state];</span><br><span style="color: hsl(120, 100%, 40%);">+  return state_chg(fi, new_state, false, timeout_secs, T, file, line);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     /* validate if new_state is a valid state */</span><br><span style="color: hsl(0, 100%, 40%);">-    if (!(st->out_state_mask & (1 << new_state))) {</span><br><span style="color: hsl(0, 100%, 40%);">-            LOGPFSMLSRC(fi, LOGL_ERROR, file, line,</span><br><span style="color: hsl(0, 100%, 40%);">-                     "transition to state %s not permitted!\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                            osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(0, 100%, 40%);">-               return -EPERM;</span><br><span style="color: hsl(0, 100%, 40%);">-  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* delete the old timer */</span><br><span style="color: hsl(0, 100%, 40%);">-      osmo_timer_del(&fi->timer);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-      if (st->onleave)</span><br><span style="color: hsl(0, 100%, 40%);">-             st->onleave(fi, new_state);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  LOGPFSMSRC(fi, file, line, "state_chg to %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                  osmo_fsm_state_name(fsm, new_state));</span><br><span style="color: hsl(0, 100%, 40%);">-        fi->state = new_state;</span><br><span style="color: hsl(0, 100%, 40%);">-       st = &fsm->states[new_state];</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-    if (timeout_secs) {</span><br><span style="color: hsl(0, 100%, 40%);">-             fi->T = T;</span><br><span style="color: hsl(0, 100%, 40%);">-           osmo_timer_schedule(&fi->timer, timeout_secs, 0);</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* Call 'onenter' last, user might terminate FSM from there */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (st->onenter)</span><br><span style="color: hsl(0, 100%, 40%);">-             st->onenter(fi, old_state);</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-  return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+/*! perform a state change while keeping the current timer running.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  This is useful to keep a timeout across several states (without having to round the</span><br><span style="color: hsl(120, 100%, 40%);">+ *  remaining time to seconds).</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  Best invoke via the osmo_fsm_inst_state_chg_keep_timer() macro which logs the source</span><br><span style="color: hsl(120, 100%, 40%);">+ *  file where the state change was effected. Alternatively, you may pass \a</span><br><span style="color: hsl(120, 100%, 40%);">+ *  file as NULL to use the normal file/line indication instead.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  All changes to the FSM instance state must be made via an osmo_fsm_inst_state_chg_*</span><br><span style="color: hsl(120, 100%, 40%);">+ *  function.  It verifies that the existing state actually permits a</span><br><span style="color: hsl(120, 100%, 40%);">+ *  transition to new_state.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] fi FSM instance whose state is to change</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] new_state The new state into which we should change</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] file Calling source file (from osmo_fsm_inst_state_chg macro)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] line Calling source line (from osmo_fsm_inst_state_chg macro)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 on success; negative on error</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+int _osmo_fsm_inst_state_chg_keep_timer(struct osmo_fsm_inst *fi, uint32_t new_state,</span><br><span style="color: hsl(120, 100%, 40%);">+                                   const char *file, int line)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        return state_chg(fi, new_state, true, 0, 0, file, line);</span><br><span> }</span><br><span> </span><br><span> /*! dispatch an event to an osmocom finite state machine instance</span><br><span>diff --git a/tests/fsm/fsm_test.c b/tests/fsm/fsm_test.c</span><br><span>index e34164c..34a8399 100644</span><br><span>--- a/tests/fsm/fsm_test.c</span><br><span>+++ b/tests/fsm/fsm_test.c</span><br><span>@@ -266,6 +266,89 @@</span><br><span>   osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+const struct timeval fake_time_start_time = { 123, 456 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define fake_time_passes(secs, usecs) do \</span><br><span style="color: hsl(120, 100%, 40%);">+{ \</span><br><span style="color: hsl(120, 100%, 40%);">+   struct timeval diff; \</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_gettimeofday_override_add(secs, usecs); \</span><br><span style="color: hsl(120, 100%, 40%);">+        osmo_clock_override_add(CLOCK_MONOTONIC, secs, usecs * 1000); \</span><br><span style="color: hsl(120, 100%, 40%);">+       timersub(&osmo_gettimeofday_override_time, &fake_time_start_time, &diff); \</span><br><span style="color: hsl(120, 100%, 40%);">+       fprintf(stderr, "Total time passed: %d.%06d s\n", \</span><br><span style="color: hsl(120, 100%, 40%);">+         (int)diff.tv_sec, (int)diff.tv_usec); \</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_timers_prepare(); \</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_timers_update(); \</span><br><span style="color: hsl(120, 100%, 40%);">+} while (0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+void fake_time_start()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct timespec *clock_override;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_gettimeofday_override_time = fake_time_start_time;</span><br><span style="color: hsl(120, 100%, 40%);">+       osmo_gettimeofday_override = true;</span><br><span style="color: hsl(120, 100%, 40%);">+    clock_override = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(clock_override);</span><br><span style="color: hsl(120, 100%, 40%);">+  clock_override->tv_sec = fake_time_start_time.tv_sec;</span><br><span style="color: hsl(120, 100%, 40%);">+      clock_override->tv_nsec = fake_time_start_time.tv_usec * 1000;</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_clock_override_enable(CLOCK_MONOTONIC, true);</span><br><span style="color: hsl(120, 100%, 40%);">+    fake_time_passes(0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int timeout_fired = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+static int timer_cb(struct osmo_fsm_inst *fi)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ timeout_fired = fi->T;</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static void test_state_chg_keep_timer()</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    struct osmo_fsm_inst *fi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   fprintf(stderr, "\n--- %s()\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        fsm.timer_cb = timer_cb;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Test that no timer remains no timer */</span><br><span style="color: hsl(120, 100%, 40%);">+     fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_fsm_inst_state_chg(fi, ST_ONE, 0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+    timeout_fired = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_state_chg_keep_timer(fi, ST_TWO);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(timeout_fired == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_ASSERT(fi->T == 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Test that a set time continues with exact precision */</span><br><span style="color: hsl(120, 100%, 40%);">+     fake_time_start();</span><br><span style="color: hsl(120, 100%, 40%);">+    fi = osmo_fsm_inst_alloc(&fsm, g_ctx, NULL, LOGL_DEBUG, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(fi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    osmo_fsm_inst_state_chg(fi, ST_ONE, 10, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        timeout_fired = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ fake_time_passes(2, 342);</span><br><span style="color: hsl(120, 100%, 40%);">+     osmo_fsm_inst_state_chg_keep_timer(fi, ST_TWO);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     fake_time_passes(0, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(timeout_fired == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   fake_time_passes(7, 1000000 - 342 - 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(timeout_fired == -1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   fake_time_passes(0, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_ASSERT(timeout_fired == 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   osmo_fsm_inst_term(fi, OSMO_FSM_TERM_REQUEST, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        fprintf(stderr, "--- %s() done\n", __func__);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct log_info_cat default_categories[] = {</span><br><span>    [DMAIN] = {</span><br><span>          .name = "DMAIN",</span><br><span>@@ -306,6 +389,7 @@</span><br><span>     osmo_fsm_inst_free(finst);</span><br><span> </span><br><span>       test_id_api();</span><br><span style="color: hsl(120, 100%, 40%);">+        test_state_chg_keep_timer();</span><br><span> </span><br><span>     osmo_fsm_unregister(&fsm);</span><br><span>       exit(0);</span><br><span>diff --git a/tests/fsm/fsm_test.err b/tests/fsm/fsm_test.err</span><br><span>index 3237def..85606e2 100644</span><br><span>--- a/tests/fsm/fsm_test.err</span><br><span>+++ b/tests/fsm/fsm_test.err</span><br><span>@@ -80,4 +80,24 @@</span><br><span> Test_FSM(arbitrary_id){NULL}: Terminating (cause = OSMO_FSM_TERM_REQUEST)</span><br><span> Test_FSM(arbitrary_id){NULL}: Freeing instance</span><br><span> Test_FSM(arbitrary_id){NULL}: Deallocated</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>\ No newline at end of file</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+--- test_state_chg_keep_timer()</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{NULL}: Allocated</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{NULL}: state_chg to ONE</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{ONE}: state_chg to TWO</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST)</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Freeing instance</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Deallocated</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 0.000000 s</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{NULL}: Allocated</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{NULL}: state_chg to ONE</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 2.000342 s</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{ONE}: state_chg to TWO</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 2.000342 s</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 9.999999 s</span><br><span style="color: hsl(120, 100%, 40%);">+Total time passed: 10.000000 s</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Timeout of T10</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Terminating (cause = OSMO_FSM_TERM_REQUEST)</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Freeing instance</span><br><span style="color: hsl(120, 100%, 40%);">+Test_FSM{TWO}: Deallocated</span><br><span style="color: hsl(120, 100%, 40%);">+--- test_state_chg_keep_timer() done</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/9389">change 9389</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/9389"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmocore </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I3c0e53b846b2208bd201ace99777f2286ea39ae8 </div>
<div style="display:none"> Gerrit-Change-Number: 9389 </div>
<div style="display:none"> Gerrit-PatchSet: 2 </div>
<div style="display:none"> Gerrit-Owner: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>