How can you react to a state machine being stopped

Given the following state machine, how can you make it react to the machine being externally stopped? We want to be able to react to the "requestFinalState()" action of the state machine to gracefully transition from SEARCH to STOP, but there doesn't seem to be any way to react to that transition. The state machine is in automatic mode.

Without this capability we get the following error in automatic mode. In reactive mode, the deployer simply locks up when told to quit.

5194.191 [CRITICAL][DeploymentComponent::stopComponents] StateMachineProcessor failed to bring StateMachine Detect into the final state. Program stalled in state 'SEARCH' line number 97


StateMachine Detect_SM
{
...
state SEARCH
{
handle
{
// until we find it ...
while true
{
while some-condition
{
... compute some parameters ...
do doSomething(parameters)
do nothing // wait for next execution period
}
}
}
transition detected() select ACQUIRED
}

state ACQUIRED
{
...
}

final state STOP
{
}
}

How can you react to a state machine being stopped

On Wed, Jul 8, 2009 at 19:21, <kiwi [dot] net [..] ...> wrote:
> Given the following state machine, how can you make it react to the machine being externally stopped? We want to be able to react to the "requestFinalState()" action of the state machine to gracefully transition from SEARCH to STOP, but there doesn't seem to be any way to react to that transition. The state machine is in automatic mode.

Maybe the best solution is to not really 'stop' the state machine, but
cause an event transition to your own 'stopped' state, while the state
machine remains in automatic or reactive mode. So the SM is only
entering the final state when it is destroyed by the component.

Useful ?

Peter

How can you react to a state machine being stopped

On Jul 10, 2009, at 09:01 , Peter Soetens wrote:

> On Wed, Jul 8, 2009 at 19:21, <kiwi [dot] net [..] ...> wrote:
>> Given the following state machine, how can you make it react to the
>> machine being externally stopped? We want to be able to react to
>> the "requestFinalState()" action of the state machine to gracefully
>> transition from SEARCH to STOP, but there doesn't seem to be any
>> way to react to that transition. The state machine is in automatic
>> mode.
>
> Maybe the best solution is to not really 'stop' the state machine, but
> cause an event transition to your own 'stopped' state, while the state
> machine remains in automatic or reactive mode. So the SM is only
> entering the final state when it is destroyed by the component.
>
> Useful ?

Hmmm ... how do you see this being implemented? What we're trying to
do is cleanly shutdown when the deployer is told to quit by the user.
I think that the time that the component becomes aware of that, is
when breakUpdateHook() or stop() are called. By then, the state
machine is no longer reacting to events, right? So how can we
facilitate a transition?

Stephen

How can you react to a state machine being stopped

On Tue, Jul 21, 2009 at 13:46, Stephen Roderick<kiwi [dot] net [..] ...> wrote:
> On Jul 10, 2009, at 09:01 , Peter Soetens wrote:
>
>> On Wed, Jul 8, 2009 at 19:21, <kiwi [dot] net [..] ...> wrote:
>>>
>>> Given the following state machine, how can you make it react to the
>>> machine being externally stopped? We want to be able to react to the
>>> "requestFinalState()" action of the state machine to gracefully transition
>>> from SEARCH to STOP, but there doesn't seem to be any way to react to that
>>> transition. The state machine is in automatic mode.
>>
>> Maybe the best solution is to not really 'stop' the state machine, but
>> cause an event transition to your own 'stopped' state, while the state
>> machine remains in automatic or reactive mode. So the SM is only
>> entering the final state when it is destroyed by the component.
>>
>> Useful ?
>
> Hmmm ... how do you see this being implemented? What we're trying to do is
> cleanly shutdown when the deployer is told to quit by the user. I think that
> the time that the component becomes aware of that, is when breakUpdateHook()
> or stop() are called. By then, the state machine is no longer reacting to
> events, right? So how can we facilitate a transition?

This is tricky. By 'quit by the user', you mean the user typing 'quit'
at the TaskBrowser prompt ? After 'quit', the TB jumps out the loop()
and the deployer and all components are stopped from its destructor.
Once stop() is called, a component no longer processes events.

The deployer could be extended with two events (application
started/stopped) which are raised from the ORO_main before/after
tb.loop(). But this looks more like a workaround since the proper
action is to have start() and stop() emitting events *and* give the
SM/EE time to react to it. Feels all very racy. It looks like
start/stop are too simplistic in application startup/shutdown
scenarios on one hand, on the other hand, it's something you want to
specify in the component only, without being dependent on other
components.

I'm sure the solution lies with events, but it looks like additional
infrastructure that guarantees that these events are emitted *and*
delivered is still lacking.

One last issue, stopHook() is being called as the last method after
the EE and processors are stopped. This guarantees thread-safety (the
component's activity is no longer running), but doesn't give you a
chance to react to stuff/control the shutdown yourself, since all SM's
are already deactivated.

Peter

How can you react to a state machine being stopped

It is not clear to me how I can use a state machine to orchestrate an orderly system shutdown. One can create a director task / thread with a state machine that handles startup quite well. However, it doesn't work to request FSM transitions from the owning components stopHook.

While one can create a director.Shutdown() method, I don't see any way to tie that in to the deployer's quit sequence.

Also, are there plans to make the deployer's behaviour on shutdown more configurable, most likely via its cpf file?

/Alex

How can you react to a state machine being stopped

It is not clear to me how I can use a state machine to orchestrate an orderly system shutdown. One can create a director task / thread with a state machine that handles startup quite well. However, it doesn't work to request FSM transitions from the owning components stopHook.

While one can create a director.Shutdown() method, I don't see any way to tie that in to the deployer's quit sequence.

Also, are there plans to make the deployer's behaviour on shutdown more configurable, most likely via its cpf file?

/Alex

How can you react to a state machine being stopped

On Tue, Nov 24, 2009 at 20:45, <alex [dot] stark [..] ...> wrote:
> It is not clear to me how I can use a state machine to orchestrate an orderly system shutdown.  One can create a director task / thread with a state machine that handles startup quite well.  However, it doesn't work to request FSM transitions from the owning components stopHook.

The thing preventing such transitions is that transitions may take
multiple steps (due to commands not being complete yet) and that
in/after stopHook, no more stepping of your script is done. The
reason transitions do work in startHook() is because right after, the
EE processes them.

>
> While one can create a director.Shutdown() method, I don't see any way to tie that in to the deployer's quit sequence.

In understand. The current way to handle this is indeed with a
'global'/'system' state machine that does all the orchestration of the
shutdown, long before the quit sequence of the deployer. In 'sane'
setups, about all components are already safely stopped when the
deployer starts cleaning up.

>
> Also, are there plans to make the deployer's behaviour on shutdown more configurable, most likely via its cpf file?

We're always open to suggestions, but If you can do it in a master SM
instead of the deployer, and let the deployer only act when the master
SM says so, it would be better.

Peter

How can you react to a state machine being stopped

On Jul 21, 2009, at 10:13 , Peter Soetens wrote:
> On Tue, Jul 21, 2009 at 13:46, Stephen Roderick<kiwi [dot] net [..] ...>
> wrote:
>> On Jul 10, 2009, at 09:01 , Peter Soetens wrote:
>>
>>> On Wed, Jul 8, 2009 at 19:21, <kiwi [dot] net [..] ...> wrote:
>>>>
>>>> Given the following state machine, how can you make it react to the
>>>> machine being externally stopped? We want to be able to react to
>>>> the
>>>> "requestFinalState()" action of the state machine to gracefully
>>>> transition
>>>> from SEARCH to STOP, but there doesn't seem to be any way to
>>>> react to that
>>>> transition. The state machine is in automatic mode.
>>>
>>> Maybe the best solution is to not really 'stop' the state machine,
>>> but
>>> cause an event transition to your own 'stopped' state, while the
>>> state
>>> machine remains in automatic or reactive mode. So the SM is only
>>> entering the final state when it is destroyed by the component.
>>>
>>> Useful ?
>>
>> Hmmm ... how do you see this being implemented? What we're trying
>> to do is
>> cleanly shutdown when the deployer is told to quit by the user. I
>> think that
>> the time that the component becomes aware of that, is when
>> breakUpdateHook()
>> or stop() are called. By then, the state machine is no longer
>> reacting to
>> events, right? So how can we facilitate a transition?
>
> This is tricky. By 'quit by the user', you mean the user typing 'quit'
> at the TaskBrowser prompt ? After 'quit', the TB jumps out the loop()
> and the deployer and all components are stopped from its destructor.
> Once stop() is called, a component no longer processes events.

Yes. User typing "quit". As a matter of interest, is there a remote
way to get the deployer to shut itself down? I don't remember ever
seeing one ... though maybe "do deployer.stop()"?

> The deployer could be extended with two events (application
> started/stopped) which are raised from the ORO_main before/after
> tb.loop(). But this looks more like a workaround since the proper
> action is to have start() and stop() emitting events *and* give the
> SM/EE time to react to it. Feels all very racy. It looks like
> start/stop are too simplistic in application startup/shutdown
> scenarios on one hand, on the other hand, it's something you want to
> specify in the component only, without being dependent on other
> components.
>
> I'm sure the solution lies with events, but it looks like additional
> infrastructure that guarantees that these events are emitted *and*
> delivered is still lacking.

Agreed. I think the proper solution would be start/stop application
events, but that "need to keep running for N seconds/cycles after the
stop event" makes me shudder. Of course, GUI toolkits have been doing
this for ages. Emit the event, keep running, and let the application
initiate the actual quit action rather than the GUI. Wonder if the
same mindset would work for us? (despite the fact that it is quite
different from our current approach).

Let me go back and look at the state machine and see if I can
reformulate it another way. We hit this only in a handful of our state
machines, but it is more than one for sure. I've also hit it hard in
another non-periodic example I'm working up.

As a side note, if I have a state machine that does several things
within a state, say changing variable values, running a loop (all
within the state machine, no method calls), and it does one method
call and then a "do nothing" after that, how many cycles does that
take? Does it do all the state-machine-level variable manipulation,
then do the method call, and then do the "do nothing", all in one
cycle? Or is all this work somehow broken up across multiple state
machine execution cycles?

Cheers
Stephen

How can you react to a state machine being stopped

On Wed, Jul 22, 2009 at 03:13, Stephen Roderick<kiwi [dot] net [..] ...> wrote:
> On Jul 21, 2009, at 10:13 , Peter Soetens wrote:
>>
>> On Tue, Jul 21, 2009 at 13:46, Stephen Roderick<kiwi [dot] net [..] ...> wrote:
>>>
>>> On Jul 10, 2009, at 09:01 , Peter Soetens wrote:
>>>
>>>> On Wed, Jul 8, 2009 at 19:21, <kiwi [dot] net [..] ...> wrote:
>>>>>
>>>>> Given the following state machine, how can you make it react to the
>>>>> machine being externally stopped? We want to be able to react to the
>>>>> "requestFinalState()" action of the state machine to gracefully
>>>>> transition
>>>>> from SEARCH to STOP, but there doesn't seem to be any way to react to
>>>>> that
>>>>> transition. The state machine is in automatic mode.
>>>>
>>>> Maybe the best solution is to not really 'stop' the state machine, but
>>>> cause an event transition to your own 'stopped' state, while the state
>>>> machine remains in automatic or reactive mode. So the SM is only
>>>> entering the final state when it is destroyed by the component.
>>>>
>>>> Useful ?
>>>
>>> Hmmm ... how do you see this being implemented? What we're trying to do
>>> is
>>> cleanly shutdown when the deployer is told to quit by the user. I think
>>> that
>>> the time that the component becomes aware of that, is when
>>> breakUpdateHook()
>>> or stop() are called. By then, the state machine is no longer reacting to
>>> events, right? So how can we facilitate a transition?
>>
>> This is tricky. By 'quit by the user', you mean the user typing 'quit'
>> at the TaskBrowser prompt ? After 'quit', the TB jumps out the loop()
>> and the deployer and all components are stopped from its destructor.
>> Once stop() is called, a component no longer processes events.
>
> Yes. User typing "quit". As a matter of interest, is there a remote way to
> get the deployer to shut itself down? I don't remember ever seeing one ...
> though maybe "do deployer.stop()"?

The only way to let them quite remotely is by using
'cdeployer-gnulinux' which does not have the taskbrowser's readline.
It will provide you with a Orocos method 'shutdown' which kills the
ORB. Of course, you can then *only* stop your application over CORBA
and have only Ctrl-C at the prompt (which we could actually intercept
and handle a clean shutdown).

>
>> The deployer could be extended with two events (application
>> started/stopped) which are raised from the ORO_main before/after
>> tb.loop().  But this looks more like a workaround since the proper
>> action is to have start() and stop() emitting events *and* give the
>> SM/EE time to react to it. Feels all very racy. It looks like
>> start/stop are too simplistic in application startup/shutdown
>> scenarios on one hand, on the other hand, it's something you want to
>> specify in the component only, without being dependent on other
>> components.
>>
>> I'm sure the solution lies with events, but it looks like additional
>> infrastructure that guarantees that these events are emitted *and*
>> delivered is still lacking.
>
> Agreed. I think the proper solution would be start/stop application events,
> but that "need to keep running for N seconds/cycles after the stop event"
> makes me shudder. Of course, GUI toolkits have been doing this for ages.
> Emit the event, keep running, and let the application initiate the actual
> quit action rather than the GUI. Wonder if the same mindset would work for
> us? (despite the fact that it is quite different from our current approach).

What you'd actually want is returning from Running to Active (still
processing events). Once all taskcontexts entered the active state,
you can proceed with stop() and then cleanup().
However, the current state diagram does not allow this transition
(only from Active to Running, not vice versa, see
http://www.orocos.org/stable/documentation/rtt/v1.8.x/doc-xml/orocos-com...).
Also, the semantics of the Active state is to go from Stopped to
Running, not the other way around. I'm shuddering by the thought of
adding another state in there (I was already reluctant to add
'Active'), but maybe the symmetry may be what we need from a
deployment perspective.

It's a thin line between application/user states and what the TC
itself should provide. Maybe we should encourage custom deployment
sequences such that these cornercases are handled by the user instead
of by the framework (cfr midlayer mistake pattern).

>
> Let me go back and look at the state machine and see if I can reformulate it
> another way. We hit this only in a handful of our state machines, but it is
> more than one for sure. I've also hit it hard in another non-periodic
> example I'm working up.
>
> As a side note, if I have a state machine that does several things within a
> state, say changing variable values, running a loop (all within the state
> machine, no method calls), and it does one method call and then a "do
> nothing" after that, how many cycles does that take? Does it do all the
> state-machine-level variable manipulation, then do the method call, and then
> do the "do nothing", all in one cycle? Or is all this work somehow broken up
> across multiple state machine execution cycles?

It should be all executed uninterrupted until the 'do nothing'
statement. If not, it's a bug. Markus noted that 'yield' is a better
name than 'do nothing' btw. In RTT 2.0, a yield will be the only way
to give up control. Nothing will cause implicit yields anymore.

Peter

How can you react to a state machine being stopped

Given the following state machine, how can you make it react to the machine being externally stopped? We want to be able to react to the "requestFinalState()" action of the state machine to gracefully transition from SEARCH to STOP, but there doesn't seem to be any way to react to that transition. The state machine is in automatic mode.

Without this capability we get the following error in automatic mode. In reactive mode, the deployer simply locks up when told to quit.

5194.191 [CRITICAL][DeploymentComponent::stopComponents] StateMachineProcessor failed to bring StateMachine Detect into the final state. Program stalled in state 'SEARCH' line number 97

StateMachine Detect_SM
{
...
	state SEARCH
	{
		handle
		{
			// until we find it ...
			while true
			{
				while some-condition
				{
					... compute some parameters ...
					do doSomething(parameters)
					do nothing // wait for next execution period
				}
			}		
		}
		transition detected() select ACQUIRED
	}
 
	state ACQUIRED
	{
		...
	}
 
	final state STOP
	{
	}
}