Markus,
Sorry for the long overdue response. I didn't get the first
notice when
this was submitted. Anyway, maybe this will help you. If we
have states
A and B then transition from A to B and encounter an exception
in B, we could transition to an exit state. The problem we
need to
address is what if all the code in state B was not
executed? The fail-safe/exit state needs to address this. The
code changes below to the example forklift_driver.c forces an
exception. When we get a SIGSEGV signal, we call the state
machine
from the sig handler with the INVALID_EVENT event. It would
be better
to have an EXIT_ON_FAULT_EVENT event that would transition to an
EXIT state to handle this situation. The code below shows
the concept
using the existing states in the forklift example to keep
from adding
new stats/events - just a quick hack. Hope this helps, and
again sorry
for the overdue response.
tonycu
In main I add the following lines:
/* v */
strSigAction.sa_handler = vSegFaultSig;
sigemptyset(&strSigAction.sa_mask);
strSigAction.sa_flags = SA_ONESHOT;
if (sigaction(SIGSEGV, &strSigAction, NULL))
{
printf("couldn't register sig handler\n");
return(1);
}
/* ^ */
And change the iBrakeApplied function to:
#include <signal.h>
#include "forklift.h"
struct sigaction strSigAction;
void
vSegFaultSig(int iSig)
{
/* an invalid event should cause us to go into a
fail-safe mode */
printf("signal %d caught, going to fail-safe mode\n",
iSig);
forklift(INVALID_EVENT);
}
int
iBrakeApplied()
{
static int i=0;
printf("-- brake applied\n");
if (i++>0)
{
char* pch = (char*)0;
printf("causing segfault (SIGSEGV)\n");
*pch = 0;
}
return(0);
}
Then run:
[einstein]:/tmp > gcc -c forklift.c -o forklift.o
[einstein]:/tmp > gcc forklift_driver.c forklift.o -o flift
/tmp/ccSRTu9F.o: In function `main':
/tmp/ccSRTu9F.o(.text+0x3d7): the `gets' function is
dangerous and should not be used.
[einstein]:/tmp >
[einstein]:/tmp > ./flift
enter event : 1
-- forklift has been reset - engine off, lift off, and in park
enter event : 2
-- engine started
enter event : 4
-- brake applied
enter event : 5
-- brake released
enter event : 4
-- brake applied
causing segfault (SIGSEGV)
signal 11 caught, going to fail-safe mode
in fail safe mode, must reset first by entering 1
Segmentation fault
[einstein]:/tmp >
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The handling of unexpected POSIX signals is also an interesting question. It is nice to see that a solution for a mapping into a state diagram is possible for this case.
A similar use case is to integrate exceptions that are raised by the function "__throw" or statement "throw" while a transition is executed and the target state (B in your example) is not reached.
Can your library or runtime environment catch unexpected exceptions to transform them into events that can be used as usual in a state model?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The state machine itself can't handle these exceptions on
its own. The FSKC
requires the main application to collect each event and pass
it to the state
machine, unless the state/event is iterative. The main
program would need
to catch the exception, translate it to an event, and call
the fsm with the
event.
If an exception is thrown while transitioning from state A
to B, I
guess we would be stateless at that instance in time...
Interesting,
I've always thought of transitions as instantaneous. From a code
perspective, I don't see how an exception could be thrown
between
states - we should always be in some state.
Here's a different thought that may help others with
handling gracefully
detected errors. If a function can't complete, it could
return a non-zero
value and that value could be fed back to the fsm to handle
the error in
the next state. If we were half way through a code segment
and ran out of
memory, an out of memory event could be returned causing the
main program
to call the fsm with the returned non-zero value.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
A few C implementations support structured exceptions. They are a special variant of the usual error handling.
Some functions (like file and network operations) can return values while a state transition is executed that must result to a new state that is different from the normal predefined or expected state.
The handling of the return code "ENOMEM" is another good example.
A gracefully detected error must be transformed into an event that must be delivered to the finite state machine before other data is processed from the input queue or ring buffer. The FSM model should be designed to forward return values into events.
Can an "unexpected event" be connected with an error handler function in your state transition tables?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
By selecting [Edit]->[Source Settings...] and checking the
"User Defined Error Handler (0,0)" checkbox, any undefined
event will force a transition to state 0 with event 0. One
downside is the event value is lost in doing this, and
another is the function associated with [0,0] must handle
all unexpected events.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I propose that each state should have an own default case.
The deisgner or developer should have the choice to map only a few until up to all the behaviour of this "User Defined Error Handler (0,0)".
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Logged In: YES
user_id=572001
Did you hear from a solution for my design question?
Logged In: YES
user_id=141318
Markus,
Sorry for the long overdue response. I didn't get the first
notice when
this was submitted. Anyway, maybe this will help you. If we
have states
A and B then transition from A to B and encounter an exception
in B, we could transition to an exit state. The problem we
need to
address is what if all the code in state B was not
executed? The fail-safe/exit state needs to address this. The
code changes below to the example forklift_driver.c forces an
exception. When we get a SIGSEGV signal, we call the state
machine
from the sig handler with the INVALID_EVENT event. It would
be better
to have an EXIT_ON_FAULT_EVENT event that would transition to an
EXIT state to handle this situation. The code below shows
the concept
using the existing states in the forklift example to keep
from adding
new stats/events - just a quick hack. Hope this helps, and
again sorry
for the overdue response.
tonycu
In main I add the following lines:
/* v */
strSigAction.sa_handler = vSegFaultSig;
sigemptyset(&strSigAction.sa_mask);
strSigAction.sa_flags = SA_ONESHOT;
if (sigaction(SIGSEGV, &strSigAction, NULL))
{
printf("couldn't register sig handler\n");
return(1);
}
/* ^ */
And change the iBrakeApplied function to:
#include <signal.h>
#include "forklift.h"
struct sigaction strSigAction;
void
vSegFaultSig(int iSig)
{
/* an invalid event should cause us to go into a
fail-safe mode */
printf("signal %d caught, going to fail-safe mode\n",
iSig);
forklift(INVALID_EVENT);
}
int
iBrakeApplied()
{
static int i=0;
printf("-- brake applied\n");
if (i++>0)
{
char* pch = (char*)0;
printf("causing segfault (SIGSEGV)\n");
*pch = 0;
}
return(0);
}
Then run:
[einstein]:/tmp > gcc -c forklift.c -o forklift.o
[einstein]:/tmp > gcc forklift_driver.c forklift.o -o flift
/tmp/ccSRTu9F.o: In function `main':
/tmp/ccSRTu9F.o(.text+0x3d7): the `gets' function is
dangerous and should not be used.
[einstein]:/tmp >
[einstein]:/tmp > ./flift
enter event : 1
-- forklift has been reset - engine off, lift off, and in park
enter event : 2
-- engine started
enter event : 4
-- brake applied
enter event : 5
-- brake released
enter event : 4
-- brake applied
causing segfault (SIGSEGV)
signal 11 caught, going to fail-safe mode
in fail safe mode, must reset first by entering 1
Segmentation fault
[einstein]:/tmp >
Logged In: YES
user_id=572001
The handling of unexpected POSIX signals is also an interesting question. It is nice to see that a solution for a mapping into a state diagram is possible for this case.
A similar use case is to integrate exceptions that are raised by the function "__throw" or statement "throw" while a transition is executed and the target state (B in your example) is not reached.
Can your library or runtime environment catch unexpected exceptions to transform them into events that can be used as usual in a state model?
Logged In: YES
user_id=141318
The state machine itself can't handle these exceptions on
its own. The FSKC
requires the main application to collect each event and pass
it to the state
machine, unless the state/event is iterative. The main
program would need
to catch the exception, translate it to an event, and call
the fsm with the
event.
If an exception is thrown while transitioning from state A
to B, I
guess we would be stateless at that instance in time...
Interesting,
I've always thought of transitions as instantaneous. From a code
perspective, I don't see how an exception could be thrown
between
states - we should always be in some state.
Here's a different thought that may help others with
handling gracefully
detected errors. If a function can't complete, it could
return a non-zero
value and that value could be fed back to the fsm to handle
the error in
the next state. If we were half way through a code segment
and ran out of
memory, an out of memory event could be returned causing the
main program
to call the fsm with the returned non-zero value.
Logged In: YES
user_id=572001
A few C implementations support structured exceptions. They are a special variant of the usual error handling.
Some functions (like file and network operations) can return values while a state transition is executed that must result to a new state that is different from the normal predefined or expected state.
The handling of the return code "ENOMEM" is another good example.
A gracefully detected error must be transformed into an event that must be delivered to the finite state machine before other data is processed from the input queue or ring buffer. The FSM model should be designed to forward return values into events.
Can an "unexpected event" be connected with an error handler function in your state transition tables?
Logged In: YES
user_id=141318
By selecting [Edit]->[Source Settings...] and checking the
"User Defined Error Handler (0,0)" checkbox, any undefined
event will force a transition to state 0 with event 0. One
downside is the event value is lost in doing this, and
another is the function associated with [0,0] must handle
all unexpected events.
Logged In: YES
user_id=572001
I propose that each state should have an own default case.
The deisgner or developer should have the choice to map only a few until up to all the behaviour of this "User Defined Error Handler (0,0)".
Logged In: YES
user_id=141318
OK, I'd be happy to accept code changes implementing this
feature.