Review at

fsm: allow graceful exit on FSM termination

The function _osmo_fsm_inst_term() terminates all child FSMs befor
it calls fi->fsm_cleanup(). This prevents the cleanup callback to
perform last actions on the child FSMs (e.g.

- Since moving the cleanup callack to the beginning of the function
  would alter the termination behavior and possibly cause malfunction
  in already existing implementation that use OSMO fsm, a new
  optional callback that is called immediately at the beginning of
  the terminatopn process is added.

Change-Id: I0fdda9fe994753f975a658c0f3fb3615949cc8bb
Closes: OS#2915
M include/osmocom/core/fsm.h
M src/fsm.c
3 files changed, 16 insertions(+), 2 deletions(-)

  git pull ssh:// refs/changes/52/6452/1

index 782ba19..928b18d 100644
@@ -10,3 +10,4 @@
 core           msgb_queue_free()       add inline func to msgb.h
 coding         gsm0503_rach_ext-encode()       add func to gsm0503_coding.h
 codec          ecu.c / ecu.h                   implement ECU for FR (Error 
Concealment Unit)
+fsm            fsmc / fsm.h                    added callback for graceful 
exit => ABI changed
\ No newline at end of file
diff --git a/include/osmocom/core/fsm.h b/include/osmocom/core/fsm.h
index 8f550d1..1b4dcee 100644
--- a/include/osmocom/core/fsm.h
+++ b/include/osmocom/core/fsm.h
@@ -69,6 +69,8 @@
        uint32_t allstate_event_mask;
        /*! function pointer to be called for allstate events */
        void (*allstate_action)(struct osmo_fsm_inst *fi, uint32_t event, void 
+       /*! graceful exit function, called at the beginning of termination */
+       void (*grace)(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause cause);
        /*! clean-up function, called during termination */
        void (*cleanup)(struct osmo_fsm_inst *fi, enum osmo_fsm_term_cause 
        /*! timer call-back for states with time-out.
diff --git a/src/fsm.c b/src/fsm.c
index d8751c9..859f7a9 100644
--- a/src/fsm.c
+++ b/src/fsm.c
@@ -279,7 +279,11 @@
 /*! unlink child FSM from its parent FSM.
  *  \param[in] fi Descriptor of the child FSM to unlink.
- *  \param[in] ctx New talloc context */
+ *  \param[in] ctx New talloc context
+ *
+ * Never call this function from the cleanup callback, because at that time
+ * the child FSMs will already be terminated. If unlinking should be performed
+ * on FSM termination, use the grace callback instead. */
 void osmo_fsm_inst_unlink_parent(struct osmo_fsm_inst *fi, void *ctx)
        if (fi->proc.parent) {
@@ -293,7 +297,10 @@
 /*! change parent instance of an FSM.
  *  \param[in] fi Descriptor of the to-be-allocated FSM.
  *  \param[in] new_parent New parent FSM instance.
- *  \param[in] new_parent_term_event Event to be sent to parent when 
terminating. */
+ *  \param[in] new_parent_term_event Event to be sent to parent when 
+ *
+ * Never call this function from the cleanup callback!
+ * (see also osmo_fsm_inst_unlink_parent()).*/
 void osmo_fsm_inst_change_parent(struct osmo_fsm_inst *fi,
                                 struct osmo_fsm_inst *new_parent,
                                 uint32_t new_parent_term_event)
@@ -509,6 +516,10 @@
        LOGPFSMSRC(fi, file, line, "Terminating (cause = %s)\n",
+       /* graceful exit (optional) */
+       if (fi->fsm->grace)
+               fi->fsm->grace(fi, cause);
        _osmo_fsm_inst_term_children(fi, OSMO_FSM_TERM_PARENT, NULL,
                                     file, line);

To view, visit
To unsubscribe, visit

Gerrit-MessageType: newchange
Gerrit-Change-Id: I0fdda9fe994753f975a658c0f3fb3615949cc8bb
Gerrit-PatchSet: 1
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Owner: dexter <>

Reply via email to