Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

AF error reporting and handling

Do you guys think error handling should be built into the framework? My noob thoughts are that all the VI for override (actor core, stop core, ...) and any vi created for dispatch (dynamic or static) should have, in the template an error handler.

This way, it would be easy to implement codes on what to do in case of error (but would also give the options of not doing anything). I think this error handler would also be a class.

I just don't know enough to implement it confidently, and it may not even be the best solution.

Bottom line, we need a simple (as possible) and straightforward way to deal with errors in AF.

Thoughts please?

0 Kudos
Message 1 of 16
(9,526 Views)

Look at "Handle Error.vi". This is built into the framework already. It is called in actor core when there is an error. Override when you want to handle the error on the spot. You can decide if you want to stop the actor on that error too. Default is to stop. Note, when an actor stops it also sends a "Last Ack" and the actor that it sends that messagee to may need to override "Handle Last Ack Core.vi".

Dig some more.

Good luck,

Casey

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

0 Kudos
Message 2 of 16
(5,783 Views)

Isn't "Handle Error" only available after the actor has launched?

Like, if there is an error before "Call Parent Method" is executed inside actor core, would "Handle error" catch it?

If not, how would you suggest handling such a situation in AF?

0 Kudos
Message 3 of 16
(5,783 Views)

ALL OF THIS IS SUBJECT TO CHANGE IF A BETTER IDEA COMES ALONG. If you have specific solutions to improve it, please lay out the architectures that you think would help so we can consider them.

Jeannius wrote:

This way, it would be easy to implement codes on what to do in case of error (but would also give the options of not doing anything). I think this error handler would also be a class.

We went down that road at the dawn of the AF. After trying various options, we pulled way back. The current thinking is generally as follows (with various community members differing in some details):

  1. The individual method that handles a given message needs to handle the error as much as possilbe. Errors have meaning in a context generally tied to that message, not to the actor as a whole. For that reason a central actor error handler for correcting errors is not a good place for the majority of errors.
  2. When a handler method returns an error to the actor, it has to be one that has meaning to the actor. We do have the Handle Errors.vi that an actor can override to decide what to do with such errors.
    There is, by definition, no way that the actor can handle the error -- if it could handle the error then the method that generated the error could have handled it. That means there are generally only two possible actions:
    A) shutdown the actor and notify caller that there was a problem and let the caller figure out what to do
    B) Tell the caller about the error (use the Report Error Msg.lvclass included in the palettes) and then go on as if the error never happened.
    C) record in the actor's state "I am in an error state" and send a mesage to the caller asking for more instructions. While waiting for an answer, the actor may silently ignore all incoming messages, or it may queue up all received messages inside the actor state, or have them all send an error back to the sender saying "I can't handle requests right now." [The Siri Solution]
  3. Doing option 2C ("set internal state and wait for more info from caller") is not something that can be part of the framework so far as anyone has been able to suggest... it requires code for each individual actor to decide how best to record that for that actor and to set up some sort of messaging protocol with its caller to actually get more info.
  4. Doing option 2B is almost never what an actor wants to do. We just don't see this happening in real code much. And it is something that could be done from within the handling method. The closest you come is logging of errors, but which errors are worth logging is still usually a each-handler-method decision.
  5. For that reason, the AF by default considers any error not handled internal to methods to use solution 2A -- shutdown and tell caller.

Jeannius wrote:

Bottom line, we need a simple (as possible) and straightforward way to deal with errors in AF.

Bottom line, what we have today is as good as it gets, we think. You should handle errors within your methods and do whatever it takes to put the actor back in a good state at the end of the method, and send other message to other actors as needed to make them aware of your actor's state.

ALL OF THIS IS SUBJECT TO CHANGE IF A BETTER IDEA COMES ALONG. If you have specific solutions to improve it, please lay out the architectures that you think would help so we can consider them.

0 Kudos
Message 4 of 16
(5,783 Views)

Hooks for error handling are already built into the framework, in the form of Handle Error.vi and Handle Last Ack Core.vi (both dynamic dispatch methods) and Report Error (a message).

I'm sure you are familiar with the default error behavior:  when an actor's method returns an error, the actor shuts down and passes the error to its caller.  The caller, having received an error, also shuts down.  This repeats until the entire application has stopped.  It's annoying, but its the only truly default behavior we could define, because everything else requries deep knowledge of your specific application and and requirements.

If you want to handle errors within an actor, override Handle Error.  You can test for whatever error condition you want, send messages to yourself, make them your caller's problem (using Report Error), and choose whether or not to shut the actor down in response to the error.

If you use Report Error, the error will be inserted into the receiving actor as if it were generated by that actor's code.

You can change how you handle errors from a nested actor that has shut down by overriding Handle Last Ack Core.vi.  You can restart the actor, start a different actor, or whatever you need to do to handle the error at that level.

0 Kudos
Message 5 of 16
(5,783 Views)

Jeannius wrote:

Like, if there is an error before "Call Parent Method" is executed inside actor core, would "Handle error" catch it?

No. Handle Error would not handle that case. In that case, you would pass the error into the Call Parent Method and the actor would immediately shut itself back down.

This is why we recommend that any setup work that could commonly result in an error (i.e. reserving system hardware that may be contended for by other actors) be done in the Pre-Launch Init.vi. An error returned from there will keep the actor from ever launching in the first place (the caller gets an error out from Launch Nested Actor.vi or Launch Root Actor.vi).

0 Kudos
Message 6 of 16
(5,783 Views)

We went down that road at the dawn of the AF. After trying various options, we pulled way back. The current thinking is generally as follows (with various community members differing in some details):

  1. The individual method that handles a given message needs to handle the error as much as possilbe. Errors have meaning in a context generally tied to that message, not to the actor as a whole. For that reason a central actor error handler for correcting errors is not a good place for the majority of errors.
  2. When a handler method returns an error to the actor, it has to be one that has meaning to the actor. We do have the Handle Errors.vi that an actor can override to decide what to do with such errors.
    There is, by definition, no way that the actor can handle the error -- if it could handle the error then the method that generated the error could have handled it. That means there are generally only two possible actions:
    A) shutdown the actor and notify caller that there was a problem and let the caller figure out what to do
    B) Tell the caller about the error (use the Report Error Msg.lvclass included in the palettes) and then go on as if the error never happened.
    C) record in the actor's state "I am in an error state" and send a mesage to the caller asking for more instructions. While waiting for an answer, the actor may silently ignore all incoming messages, or it may queue up all received messages inside the actor state, or have them all send an error back to the sender saying "I can't handle requests right now." [The Siri Solution]
  3. Doing option 2C ("set internal state and wait for more info from caller") is not something that can be part of the framework so far as anyone has been able to suggest... it requires code for each individual actor to decide how best to record that for that actor and to set up some sort of messaging protocol with its caller to actually get more info.
  4. Doing option 2B is almost never what an actor wants to do. We just don't see this happening in real code much. And it is something that could be done from within the handling method. The closest you come is logging of errors, but which errors are worth logging is still usually a each-handler-method decision.
  5. For that reason, the AF by default considers any error not handled internal to methods to use solution 2A -- shutdown and tell caller.

Jeannius wrote:

Bottom line, we need a simple (as possible) and straightforward way to deal with errors in AF.

Bottom line, what we have today is as good as it gets, we think. You should handle errors within your methods and do whatever it takes to put the actor back in a good state at the end of the method, and send other message to other actors as needed to make them aware of your actor's state.

ALL OF THIS IS SUBJECT TO CHANGE IF A BETTER IDEA COMES ALONG. If you have specific solutions to improve it, please lay out the architectures that you think would help so we can consider them.

My thought was something along the line of option 2C. Basically something that would not only handle error during the "proper" actor looping, but also during initialization.

My current application has an error in one of the init VI. Sure, I correct the code or create codes to handle that error, but that is just one error. What if there is more unforeseen ones? I wanted a OO way of handling any error. I believe that would greatly help with actor debugging.

I was in the process of starting a project called "Actor with Error Handling". The thought was to have a direct child of actor that would override all of actor's method. The only addition would be to add a "handle error" at the end of each overriden VI. I would also want to do the same to the VI template for creating new VI for any child.

The "handle error" would be a VI from an "ERROR" class. The thought was to use the singleton pattern to always have at most one instance of the "Error" actor running. All errors would be reported back to this class and it would give the user a prompt depending on the severity of the error. User could add new error codes and type and classify them by severity. (Urgen ones would require action, others might not).

The outline define above may not be entirely within my power to develop alone. If this outline garner interest, as a noob, I was thinking of putting my work on github for anybody to help with. I also read the recent discussion about VI not posted on here, so Myself or others would periodically post the latest and greatest commit on here to avoid the legal issue.

0 Kudos
Message 7 of 16
(5,783 Views)

In order to catch errors in pre launch init I start a data logger actor that has a "log error" message. I store its enqueuer in any other actors that I want to log errors generated within pre-launch init.

With the advent of launching nested actors I also make sure that I don't automatically close the logger and instead close it as part of stop core, but with a delay so that I can log all of the errors and the shutdown sequence.

Casey Lamers


Phoenix, LLC


casey.lamers@phoenixwi.com


CLA, LabVIEW Champion


Check Out the Software Engineering Processes, Architecture, and Design track at NIWeek. 2018 I guarantee you will learn things you can use daily! I will be presenting!

0 Kudos
Message 8 of 16
(5,783 Views)

Casey: Why not just have every child that spins up send a message to the error logger that says "I'm here" and when stopping send a message "I'm gone". Then the error handler knows exactly how long to stick around... no relying on a timout.

0 Kudos
Message 9 of 16
(5,783 Views)

Jeannius:

What you propose is a good framework for building 2C, but not if you make it a *singleton*. I am 90% certain you will quickly find that you WANT a separate error handler for each actor, and it probably has a much shorter lifetime than you imagine at the moment.

Suppose you have actor Bob. One of Bob's methods generates an error code 1.

You have another actor Alice. One of Alice's methods can also generate error code 1.

A central error handler has no idea what error code 1 means in context. In fact, it can be different meanings for different methods of Bob.

What you can have is Bob launching a nested actor Ask The User Actor.lvclass. When Bob launches that actor, Bob teaches it "here's what I need you to ask the user and here are the options the user has to pick from." The new actor posts an appropriate dialog (or email or other signal) to the user and get the user's opinion. Then it sends the answer back to Bob (its caller). Then it quits. No need to keep running.

The actor that queries the user has a brief life -- only coming into existence when the error occurs and disappearing after its small task is done. The Ask The User.lvclass is an actor that you can build easily enough. Whether it should become part of the AF is a separate discusion.

Meanwhile, you have the problem of what Bob does while waiting for the user's answer. An error occurs in a method X. Inside method X, Bob records "I have a problem" and then probably overrides Receive Msg.vi so that every message that comes in after that point gets stored instead of calling its handler. But maybe there are high priority messages that cannot wait that Bob has to handle even while in an error -- messages like "emergency stop". So you have to write custom code for Bob that is likely different from the code you write for Alice when she is in a similar situation.

You only want to do all of this for errors that you know what to ask the user. What do you do with the error "no monitor connected so I can't ask the user"? In the vast majority of cases...

Jeannius wrote:

What if there is more unforeseen ones?

...unforseen errors should shut down the actor. Which they will if you just wire the error cluster.

Do you see the difference between what I'm suggesting and the way you're proposing it? Same Actor class concept but a very different way of using it.

0 Kudos
Message 10 of 16
(5,783 Views)