title: How do I get boost.msm to properly change state when using a signal handler to trigger events?
body: <p>My (<code>boost.msm</code>) state machine appears to 'roll-back' when using signal handlers
  to trigger events. However, when I use direct calls to trigger events the state
  machine behaves correctly.</p>
  
  <p>I looked in the boost documentation and searched the web, but it seems that
  all of the examples use direct calls for event triggering. I also searched SO,
  but couldn't find anything addressing this topic.</p>
  
  <p>I'm in the process of learning the boost meta state machine library to see if
  it would be useful to replace the existing "home grown" state machine library
  currently used by my development team.</p>
  
  <p>In order for this to work, I'll need to be able to trigger state machine events
  from signal handlers (handling signals from <code>boost.signals2</code>).</p>
  
  <p>I created a simple, but contrived, example to give it a test run and was
  baffled when I saw that after the first event was triggered, the state
  machine correctly (but temporarily) changed states (while in the signal handler)
  but apparently 'rolled back' after returning to main.</p>
  
  <p>When I bypassed the signal handlers (by using direct calls to process_event)
  everything worked correctly.</p>
  
  <p>The, admittedly contrived, test state machine is designed to do this:</p>
  
  <pre><code>[state_a]--event_a--&gt;[state_b]--event_b--&gt;[state_c]--event_c--&gt;{back-to-state_a}
  </code></pre>
  
  <p>I would like to know how I can make this design (or something similar) work
  using signal handlers to trigger state machine events correctly. Using direct
  calls isn't an option for me since I only receive signals to work with.</p>
  
  <p>I've included the test code below. Note that the first half of the main
  function exercises the signal handler triggering and the second half of main
  exercises the direct call triggering 
  (compiled using <code>g++ main.cpp -omain' or 'clang++ main.cpp -omain</code>):</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;boost/signals2.hpp&gt;
  #include &lt;boost/shared_ptr.hpp&gt;
  #include &lt;boost/msm/back/state_machine.hpp&gt;
  #include &lt;boost/msm/back/tools.hpp&gt;
  #include &lt;boost/msm/front/state_machine_def.hpp&gt;
  #include &lt;boost/msm/front/functor_row.hpp&gt;
  
  typedef boost::signals2::signal&lt;void()&gt; sig1_t;
  
  //================================================================================
  // ------- Sensors section
  
  struct sensor_a {
    sig1_t&amp; get_sig() { return sig; }
    void emit() { sig(); }
  
  private:
    sig1_t sig;
  };
  
  struct sensor_b {
    sig1_t&amp; get_sig() { return sig; }
    void emit() { sig(); }
  
  private:
    sig1_t sig;
  };
  
  struct sensor_c {
    sig1_t&amp; get_sig() { return sig; }
    void emit() { sig(); }
  
  private:
    sig1_t sig;
  };
  
  //========================================
  // Sensors class
  struct Sensors {
    sensor_a&amp; get_sa() {
      return sa;
    }
  
    sensor_b&amp; get_sb() {
      return sb;
    }
  
    sensor_c&amp; get_sc() {
      return sc;
    }
  
  private:
    sensor_a sa;
    sensor_b sb;
    sensor_c sc;
  };
  
  // ----- Events
  struct event_a {
    std::string name() const { return "event_a"; }
  };
  struct event_b {
    std::string name() const { return "event_b"; }
  };
  struct event_c {
    std::string name() const { return "event_c"; }
  };
  struct exit {
    std::string name() const { return "exit"; }
  };
  
  //================================================================================
  // ----- State machine section
  
  namespace msm = boost::msm;
  namespace msmf = boost::msm::front;
  namespace mpl = boost::mpl;
  
  class Controller;  // forward declaration
  
  //========================================
  // testmachine class (the state machine)
  struct testmachine : msmf::state_machine_def&lt;testmachine&gt;
  {
    testmachine(Controller&amp; c) : controller(c) {}
  
    template &lt;class Fsm,class Event&gt;
    void no_transition(Event const&amp; e, Fsm&amp; ,int state) {
      std::cout &lt;&lt; "testmachine::no_transition -- No transition for event: '"
                &lt;&lt; e.name() &lt;&lt; "'" &lt;&lt; " on state: " &lt;&lt; state &lt;&lt; std::endl;
    }
  
    //---------
    struct state_a : msmf::state&lt;&gt; {
      template &lt;class Event,class Fsm&gt;
      void on_entry(Event const&amp;, Fsm&amp;) const {
        std::cout &lt;&lt; "state_a::on_entry() " &lt;&lt; std::endl;
      }
  
      template &lt;class Event,class Fsm&gt;
      void on_exit(Event const&amp;, Fsm&amp;) const {
        std::cout &lt;&lt; "state_a::on_exit()" &lt;&lt; std::endl;
      }
    };
  
    //---------
    struct state_b : msmf::state&lt;&gt; {
      template &lt;class Event,class Fsm&gt;
      void on_entry(Event const&amp; e, Fsm&amp;) const {
        std::cout &lt;&lt; "state_b::on_entry() -- event: " &lt;&lt; e.name() &lt;&lt; std::endl;
      }
  
      template &lt;class Event,class Fsm&gt;
      void on_exit(Event const&amp; e, Fsm&amp;) const {
        std::cout &lt;&lt; "state_b::on_exit() -- event: " &lt;&lt; e.name() &lt;&lt; std::endl;
      }
    };
  
    //---------
    struct state_c : msmf::state&lt;&gt; {
      template &lt;class Event,class Fsm&gt;
      void on_entry(Event const&amp; e, Fsm&amp;) const {
        std::cout &lt;&lt; "state_c::on_entry() -- event: " &lt;&lt; e.name() &lt;&lt; std::endl;
      }
  
      template &lt;class Event,class Fsm&gt;
      void on_exit(Event const&amp; e, Fsm&amp;) const {
        std::cout &lt;&lt; "state_c::on_exit() -- event: " &lt;&lt; e.name() &lt;&lt; std::endl;
      }
    };
  
    //---------
    // Set initial state
    typedef mpl::vector&lt;state_a&gt; initial_state;
  
    //---------
    // Transition table
    struct transition_table:mpl::vector&lt;
      //          Start      Event           Next       Action      Guard
      msmf::Row &lt; state_a,   event_a,        state_b,   msmf::none, msmf::none &gt;,
      msmf::Row &lt; state_b,   event_b,        state_c,   msmf::none, msmf::none &gt;,
      msmf::Row &lt; state_c,   event_c,        state_a,   msmf::none, msmf::none &gt;
      &gt; {};
  
  private:
    Controller&amp; controller;
  };
  
  // state-machine back-end
  typedef msm::back::state_machine&lt;testmachine&gt; TestMachine;
  
  //================================================================================
  // --------- controller section
  
  namespace msm = boost::msm;
  namespace mpl = boost::mpl;
  
  // debug print helper:
  std::string demangle(const std::string&amp; mangled) {
    int status;
    char* c_name = abi::__cxa_demangle(mangled.c_str(), 0, 0, &amp;status);
  
    if(c_name){
      std::string retval(c_name);
      free((void*)c_name);
      return retval;
    }
  
    return mangled;
  }
  
  // debug print helper (from boost msm documentation):
  void pstate(TestMachine const&amp; sm) {
    typedef TestMachine::stt Stt;
    typedef msm::back::generate_state_set&lt;Stt&gt;::type all_states;
    static char const* state_names[mpl::size&lt;all_states&gt;::value];
    mpl::for_each&lt;all_states,boost::msm::wrap&lt;mpl::placeholders::_1&gt; &gt;
      (msm::back::fill_state_names&lt;Stt&gt;(state_names));
  
    for (unsigned int i=0;i&lt;TestMachine::nr_regions::value;++i){
      std::cout &lt;&lt; " -&gt; " &lt;&lt; demangle(state_names[sm.current_state()[i]])
                &lt;&lt; std::endl;
    }
  }
  
  //========================================
  // Controller class
  struct Controller {
    Controller(Sensors&amp; s) :
      sensors(s),
      tm(boost::ref(*this)) {
      s.get_sa().get_sig().connect(boost::bind(&amp;Controller::on_sa_event, *this));
      s.get_sb().get_sig().connect(boost::bind(&amp;Controller::on_sb_event, *this));
      s.get_sc().get_sig().connect(boost::bind(&amp;Controller::on_sc_event, *this));
      tm.start();
    }
  
    void on_sa_event() {
      std::cout &lt;&lt; "Controller::on_sa_event function entered ++++++++" &lt;&lt; std::endl;
      current_state(__FUNCTION__);
      trigger_event_a();
      current_state(__FUNCTION__);
      std::cout &lt;&lt; "Controller::on_sa_event function exiting --------" &lt;&lt; std::endl;
    };
  
    void on_sb_event() {
      std::cout &lt;&lt; "Controller::on_sb_event function entered ++++++++" &lt;&lt; std::endl;
      current_state(__FUNCTION__);
      trigger_event_b();
      current_state(__FUNCTION__);
      std::cout &lt;&lt; "Controller::on_sb_event function exiting --------" &lt;&lt; std::endl;
    };
  
    void on_sc_event() {
      std::cout &lt;&lt; "Controller::on_sc_event function entered ++++++++" &lt;&lt; std::endl;
      current_state(__FUNCTION__);
      trigger_event_c();
      current_state(__FUNCTION__);
      std::cout &lt;&lt; "Controller::on_sc_event function exiting --------" &lt;&lt; std::endl;
    };
  
    // debug print function
    void current_state(const std::string&amp; f) {
      std::cout &lt;&lt; "\nController::current_state ("
                &lt;&lt; "called from function: " &lt;&lt; f
                &lt;&lt;")" &lt;&lt; std::endl;
      pstate(tm);
      std::cout &lt;&lt; std::endl;
    }
  
    void trigger_event_a() {
      std::cout &lt;&lt; "Controller::trigger_event_a" &lt;&lt; std::endl;
      tm.process_event(event_a());
      current_state(__FUNCTION__);
    }
  
    void trigger_event_b() {
      std::cout &lt;&lt; "Controller::trigger_event_b" &lt;&lt; std::endl;
      tm.process_event(event_b());
      current_state(__FUNCTION__);
    }
  
    void trigger_event_c() {
      std::cout &lt;&lt; "Controller::trigger_event_c" &lt;&lt; std::endl;
      tm.process_event(event_c());
      current_state(__FUNCTION__);
    }
  
  private:
    Sensors&amp; sensors;
    TestMachine tm;
  };
  
  //================================================================================
  // --------- main
  int main() {
    Sensors sensors;
    Controller controller(sensors);
  
    std::cout &lt;&lt; "Exercise state machine using signal handlers (fails):" &lt;&lt; std::endl;
    controller.current_state("***** main");
    sensors.get_sa().emit();
  
    controller.current_state("***** main");
    sensors.get_sb().emit();
  
    controller.current_state("***** main");
    sensors.get_sc().emit();
  
    controller.current_state("***** main");
  
    std::cout &lt;&lt; "\nExercise state machine using direct calls (works):" &lt;&lt; std::endl;
    controller.current_state("***** main");
    controller.trigger_event_a();
  
    controller.current_state("***** main");
    controller.trigger_event_b();
  
    controller.current_state("***** main");
    controller.trigger_event_c();
  
    controller.current_state("***** main");
  }
  </code></pre>
  
  <p>Here is the output:</p>
  
  <pre><code> 1  state_a::on_entry()
   2  Exercise state machine using signal handlers (fails):
  
   3  Controller::current_state (called from function: ***** main)
   4   -&gt; testmachine::state_a
  
   5  Controller::on_sa_event function entered ++++++++
  
   6  Controller::current_state (called from function: on_sa_event)
   7   -&gt; testmachine::state_a
  
   8  Controller::trigger_event_a
   9  state_a::on_exit()
  10  state_b::on_entry() -- event: event_a
  
  11  Controller::current_state (called from function: trigger_event_a)
  12   -&gt; testmachine::state_b
  
  13  Controller::current_state (called from function: on_sa_event)
  14   -&gt; testmachine::state_b
  
  15  Controller::on_sa_event function exiting --------
  
  16  Controller::current_state (called from function: ***** main)
  17   -&gt; testmachine::state_a
  
  18  Controller::on_sb_event function entered ++++++++
  
  19  Controller::current_state (called from function: on_sb_event)
  20   -&gt; testmachine::state_a
  
  21  Controller::trigger_event_b
  22  testmachine::no_transition -- No transition for event: 'event_b' on state: 0
  
  23  Controller::current_state (called from function: trigger_event_b)
  24   -&gt; testmachine::state_a
  
  25  Controller::current_state (called from function: on_sb_event)
  26   -&gt; testmachine::state_a
  
  27  Controller::on_sb_event function exiting --------
  
  28  Controller::current_state (called from function: ***** main)
  29   -&gt; testmachine::state_a
  
  30  Controller::on_sc_event function entered ++++++++
  
  31  Controller::current_state (called from function: on_sc_event)
  32   -&gt; testmachine::state_a
  
  33  Controller::trigger_event_c
  34  testmachine::no_transition -- No transition for event: 'event_c' on state: 0
  
  35  Controller::current_state (called from function: trigger_event_c)
  36   -&gt; testmachine::state_a
  
  37  Controller::current_state (called from function: on_sc_event)
  38   -&gt; testmachine::state_a
  
  39  Controller::on_sc_event function exiting --------
  
  40  Controller::current_state (called from function: ***** main)
  41   -&gt; testmachine::state_a
  
  42  Exercise state machine using direct calls (works):
  
  43  Controller::current_state (called from function: ***** main)
  44   -&gt; testmachine::state_a
  
  45  Controller::trigger_event_a
  46  state_a::on_exit()
  47  state_b::on_entry() -- event: event_a
  
  48  Controller::current_state (called from function: trigger_event_a)
  49   -&gt; testmachine::state_b
  
  50  Controller::current_state (called from function: ***** main)
  51   -&gt; testmachine::state_b
  
  52  Controller::trigger_event_b
  53  state_b::on_exit() -- event: event_b
  54  state_c::on_entry() -- event: event_b
  
  55  Controller::current_state (called from function: trigger_event_b)
  56   -&gt; testmachine::state_c
  
  57  Controller::current_state (called from function: ***** main)
  58   -&gt; testmachine::state_c
  
  59  Controller::trigger_event_c
  60  state_c::on_exit() -- event: event_c
  61  state_a::on_entry() 
  
  62  Controller::current_state (called from function: trigger_event_c)
  63   -&gt; testmachine::state_a
  
  64  Controller::current_state (called from function: ***** main)
  65   -&gt; testmachine::state_a
  </code></pre>
  
  <p>I added line numbers by post-processing the output file for easier reference.</p>
  
  <p>Line 01 of the output shows that the state machine correctly transitioned from
  the initial pseudo-state to state_a.</p>
  
  <p>Line 14 of the output shows that the state machine correctly transitioned from
  state_a to state_b when inside of the on_sa_event function.</p>
  
  <p>However, line 17 shows the state machine returned to state_a when tested from
  main (!)</p>
  
  <p>The state machine remains in state_a for the remaining transitions of the
  signal handler tests (lines 18-41), resulting in a few 'No Transition' error
  messages.</p>
  
  <p>For the direct call exercise (output lines 42-65), the state machine transitions
  correctly through all states and there is no difference in it's 'current state'
  from within the triggering function and when in main (after the triggering
  function call).</p>
  
  <p>Environment:
  OS: "Ubuntu 16.04 LTS"</p>
  
  <p>g++ version: (Ubuntu 5.3.1-14ubuntu2) 5.3.1 20160413</p>
  
  <p>boost version: boost_1_60_0</p>