[Boost-users] [statechart] state_machine send_event assertion fails

240 views
Skip to first unread message

Gooding, Dustin R. (JSC-ER411)

unread,
Jun 13, 2013, 9:33:01 PM6/13/13
to boost...@lists.boost.org
Hello,

I'm a new user of statechart and for the most part am enjoying it very much.  I've implemented a state machine with about 30 states (9 orthogonal regions) and over 50 events.  It works very well and as expected, except for this one issue.  Every once in a while, and in a way I've been unable to consistently repeat, I get an assertion failure resulting in a core dump.

/usr/include/boost/statechart/state_machine.hpp:873: boost::statechart::detail::reaction_result boost::statechart::state_machine<MostDerived, InitialState, Allocator, ExceptionTranslator>::send_event(const event_base_type&) [with MostDerived = GripperPosition, InitialState = Container, Allocator = std::allocator<void>, ExceptionTranslator = boost::statechart::null_exception_translator, boost::statechart::state_machine<MostDerived, InitialState, Allocator, ExceptionTranslator>::event_base_type = boost::statechart::event_base]: Assertion `get_pointer( pOutermostUnstableState_ ) == 0' failed.

"GripperPosition" is my state_machine.  "Container" is the simple_state the state machine initially enters.  Container has no transitions, but many sub states (it's the owner of the 9 orthogonal regions).  (As far as I can tell, if the state machine is alive, then "Container" is an active state.)  "Container" has a handful of custom_reactions that essentially listen for user-supplied events, "forward" those events in to the appropriate orthogonal regions using internal-only events, and then discard the user-supplied events.  The intention here is to have a single event propagate to multiple orthogonal regions, allowing them all to react.  For example:

boost::statechart::result Container::react(const e_still&)
{
    post_event(i_still_action());
    post_event(i_still_moving());
    return discard_event();
}

I am unsure if these reactions are the cause of the assertion failure, but given that the error message says "Container" is the InitialState, I have to assume so.  Given that, I don't see how either Container or GripperPosition are inactive and don't know how to interpret this error.    I'd appreciate some guidance.

I'm running Ubuntu 12.04, GCC 4.6.3, and Boost 1.46.1.

--
Dustin Gooding
NASA/JSC Robotics

Andreas Huber

unread,
Jun 14, 2013, 7:35:52 AM6/14/13
to boost...@lists.boost.org
Hi Dustin

> boost::statechart::result Container::react(const e_still&)

> {

>     post_event(i_still_action());

>     post_event(i_still_moving());

>     return discard_event();

> }

>

>

> I am unsure if these reactions are the cause of the assertion failure,
but given that the error message says "Container" is the InitialState, I
have to assume so.  Given that, I don't see how either Container or
GripperPosition are inactive and don't know how to interpret this
error.    I'd appreciate some guidance.

Your react function looks fine. Do you by any chance directly or indirectly
call state_machine::process_event from inside the state-machine (e.g. in-
state reaction, transition, entry action, exit action, etc.)?

Thanks,

Andreas

_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Kelly, Dan

unread,
Jun 14, 2013, 7:55:10 AM6/14/13
to boost...@lists.boost.org
Dustin,

I have to agree with the last response. As long as you are calling post_event as opposed to process_event, your reaction looks fine. The issue might not be with this particular reaction. But if somewhere else you are inadvertently calling process_event while responding to a transition, you might be corrupting your state which is only later detected by this assertion.

Dan
________________________________

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Gooding, Dustin R. (JSC-ER411)

unread,
Jun 14, 2013, 9:18:38 AM6/14/13
to boost...@lists.boost.org

On Jun 14, 2013, at 6:35 AM, Andreas Huber <ahd6974-spam...@yahoo.com> wrote:

> Your react function looks fine. Do you by any chance directly or indirectly
> call state_machine::process_event from inside the state-machine (e.g. in-
> state reaction, transition, entry action, exit action, etc.)?

Thanks for the quick response.

I only call process_event directly from outside the state machine. From inside, I do call transit() in a couple of reactions. That's how I understood guards were implemented. Maybe I missed something? Some of those transit() calls are to sibling states but most are to an uncle state (sibling to parent state). I never transit() to the same state. Here's an example:

boost::statechart::result Inactive::react(const i_ready_command&)
{
if (state_downcast< const NotFaulted * >() != 0)
{
return transit<Active>();
}

return discard_event();
}

In few state's constructors, I call post_event().

--
dustin

Kelly, Dan

unread,
Jun 14, 2013, 11:59:34 AM6/14/13
to boost...@lists.boost.org
Your reaction with guard looks fine to me. I've never had a problem implementing it like this.

-- Dan

-----Original Message-----
From: Boost-users [mailto:boost-use...@lists.boost.org] On Behalf Of Gooding, Dustin R. (JSC-ER411)
Sent: Friday, June 14, 2013 9:19
To: boost...@lists.boost.org
Subject: Re: [Boost-users] [statechart] state_machinesend_event assertion fails


________________________________

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Andreas Huber

unread,
Jun 14, 2013, 4:25:25 PM6/14/13
to boost...@lists.boost.org
> I only call process_event directly from outside the state machine.

> From inside, I do call transit() in a couple of reactions. That's

> how I understood guards were implemented. Maybe I missed something?



As long as you call transit (and its relatives like e.g. terminate) only
from react functions, you're not missing anything.



> Some of

> those transit() calls are to sibling states but most are to an uncle
state (sibling to parent state). I

> never transit() to the same state.



You can transit to any state, even the one you are currently in, so no
problem here either.



> In few state's constructors, I call post_event().



That's fine too.



So far everything seems in order. The only suggestion I have is that you
try to reproduce the problem and then whittle it down to something that you
are comfortable to post or send me by private email. I know this is
sometimes hard, but the statechart internals are such that the library
should exhibit exactly the same behavior when two newly constructed FSMs of
the same type are fed the same events in the same order. So, if possible
log all events and wait for the problem to resurface?



Regards,



Andreas

Gooding, Dustin R. (JSC-ER411)

unread,
Jun 14, 2013, 4:36:59 PM6/14/13
to boost...@lists.boost.org
On Jun 14, 2013, at 3:25 PM, Andreas Huber <ahd6974-spam...@yahoo.com> wrote:

> That's fine too.

That's what's so frustrating. Everything *looks* right. And Boost, in general, is so picky about things that if it even compiles that tells me I'm on the right track.

> So, if possible log all events and wait for the problem to resurface?

That's my next step. I'll instrument before every send_event, process_event and transit. I'm also in the process of converting a bunch of custom_reactions into more appropriate things like in_state_reactions, just to eliminate unnecessary event handling on my part.

I'll post back when/if I ever nail it down. It happens very infrequently, but enough to give me heartburn.

--
dustin

Slava

unread,
Jun 17, 2013, 2:48:55 AM6/17/13
to boost...@lists.boost.org
On Fri, 14 Jun 2013 22:36:59 +0200, Gooding, Dustin R. (JSC-ER411)
<dustin.r...@nasa.gov> wrote:

> "GripperPosition" is my state_machine. "Container" is the simple_state
> the state machine initially enters. Container > has no transitions, but
> many sub states (it's the owner of the 9 orthogonal regions). (As far
> as I can tell, if the state machine is alive, then "Container" is an
> active state.) "Container" has a handful of custom_reactions that
> essentially listen for user-supplied events, "forward" those events in
> to the appropriate orthogonal regions using internal-only events, and
> then discard the user-supplied events. The intention here is to have a
> single event propagate to multiple orthogonal regions, allowing them all
> to react. For example:

AFAIK boost statechart is not thread-safe, so ensure you're not processing
the external events simultaneously.


> I'll post back when/if I ever nail it down. It happens very
> infrequently, but enough to give me heartburn.

For me the assertion condition (+comment before if available) with the
stacktrace at
the assertion moment always explained the issue. Look at
your stack trace, you'll likely see unambiguously what is causing
send_event() in an unstable state.

If the assertion is not reproducible all the time, I'd check for
memory/threading errors with valgrind tools.

-- Slava
Reply all
Reply to author
Forward
0 new messages