From 04:00 PM CDT – 08:00 PM CDT (09:00 PM UTC – 01:00 AM UTC) Tuesday, April 16, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Best Pracaces- Cleanup after error in Pre Launch Init

I have a solution for my particular issue but I wanted some feedback from the community on what other people are doing. 

 

Situation; actor application which has nested actor groups launched by a manager actors. The most nested actors have multiple levels of inheritance (eg a 'task' actor inherits from 'task core' which is responsible for a lot of the bookkeeping and resource allocation).  So anything that is allocated during Pre Launch Init is cleaned up during Stop Core. 

 

What we found is that if a error occurs during the Pre Launch Init after the task:call parent node is called (and the associated resources allocated) the resources are left hanging because stop core is never run and because the error occurred after the call parent the parent has no idea there was an error. 

 

Our solution to this was to in our base classes method of Launch Nested Actor put a check after calling root:Launch Nested Actor and if it returns an error to run stop core. 

 

I was thinking that this seems like something that could be addressed in the framework by having a vi here that could be overrideen to include stop core or any other post Pre Launch Init error. 

 

tkendall_0-1650989592163.png

 

Anybody else run into something similar? Thoughts on best practices with handling PLI errors?  

 

0 Kudos
Message 1 of 21
(1,935 Views)

You are not required to call the parent node in Pre Launch Init, so here is the recommended practice:

 

1)  First, allocate an resources required by the child actor.

2a)  If successful (no error), invoke Call Parent Node to allocate resources required in the parent class

2b)  If not successful, do any cleanup required from step 1.

 

This is what we're teaching in the AF course, and what I use in my practice.

0 Kudos
Message 2 of 21
(1,926 Views)

I never thought about any possible enhancement to the framework.

 

However, I do bundle all my reference creations in a dynamic-despatched createReferences.vi; and vice versa for destroyReferences.vi. Stop Core will indeed call the latter. Pre-Launch Init is set to invoke createReferences. If no error, invoke call-parent-method. If error from either of the prior two steps, invoke destroy references.

 

Dhakkan_0-1650990568688.png

 

Not sure if it's a best practice; but it works for me.

0 Kudos
Message 3 of 21
(1,922 Views)

Note: this is a large-is codebase and there is a good deal of legacy in it, so going though and changing everything is time prohibitive.

 

We have established that call parent node is the first thing you call in PLI as it is used for loading config values into the parent class private data (which is used by the child for more specific init and config)

 

I am not sure I am justified in my thinking that it feels more correct to have the cleanup occur outside of PLI that way no matter what the cleanup goes there. 

0 Kudos
Message 4 of 21
(1,904 Views)

Generally, since PLI doesn't call Stop Core, you should put cleanup code inside PLI. Basically just handle all errors- if there are upstream errors, deinit your resources. This handles errors generated at all levels of parents and children. You can simplify this by making a "Clean up references" subVI that runs if PLI fails and again in Stop Core. That'll reduce duplicate code.

 

I don't see a great reason to have cleanup code run outside of PLI. It feels like it'd just make things more complicated. Since PLI is non-reentrant, you're guaranteed to finish one run before another actor tries to do the same thing. Stop Core makes sense, because you never know when there will be an error so you have an "At the end of this actor's life, do this to clean up".

 

With PLI you always know immediately if there is an error. With all error wires connected, each PLI won't return until it knows that both itself and all higher up PLI's have completed their tasks. Thus, it makes more sense to keep it inside PLI. I can't think of a situation in which I want PLI to finish while reporting an error, then wait and do something else, THEN clean up the resources.

Message 5 of 21
(1,888 Views)

As a comment from an outside observer of the Actor Framework, this seems to be an architectural design weakness: a Creation point with no matching Cleanup point that is guaranteed to be called after the creation.  This leads to the need to place cleanup code in more than one place, and is a source of bug potential.  I would think the natural place for cleanup of code in PLI is in the cleanup section of "Actor.vi", after the call to "Actor Core.vi".

 

BTW, "Pre Launch Init" is also poorly named, as it is called after "Actor.vi" is async-called/launched.  It is really "Pre Calling of Actor Core", and could do with a "Post Calling of Actor Core" to match.

 

Also, side question: isn't "Actor Core" itself a more natural place to initialize and cleanup references?  What is the purpose of doing this in "Pre Launch Init"?  

0 Kudos
Message 6 of 21
(1,856 Views)

My method for allocating dynamic resources is to create an action called "After Launch Init" with an associated message. Call this message first with high priority before your actor core.vi enters the parent actor core. This way, After Core Init.vi will be called first in any case. The advantage of the method is that your nested actors will be cleaned up by the standard AF mechanism if something goes wrong.

0 Kudos
Message 7 of 21
(1,848 Views)

@drjdpowell wrote:

Also, side question: isn't "Actor Core" itself a more natural place to initialize and cleanup references?  What is the purpose of doing this in "Pre Launch Init"?  


Actor Core isn't mutually exclusive with all other actors, so it doesn't provide a venue for safe acquisition of system resources. Actor Core IS where you initialize references that do not need system-wide mutual exclusion.

0 Kudos
Message 8 of 21
(1,841 Views)

@t.kendall wrote:

We have established that call parent node is the first thing you call in PLI as it is used for loading config values into the parent class private data (which is used by the child for more specific init and config)


Good. That's often important -- it follows the pattern of constructors from other programming languages. By not having "error in" on that node, most people luck into that pattern without being taught so that they can chain the error wire through everything else.

 


@t.kendall wrote:

I am not sure I am justified in my thinking that it feels more correct to have the cleanup occur outside of PLI that way no matter what the cleanup goes there. 


If an error occurs inside PLI, no other part of the actor will execute (by design), so you need to rollback any acquired resources if there's an error. Standard pattern should be

 

  1. Call Parent Node
  2. If and only if no error, do this class' acquisition of resources. Eg:
    1. Acquire resource A
    2. Acquire resource B
    3. Acquire resource C
  3. If error in step 2, release this class' acquisition of resources (ancestors already released theirs if they had an error). Eg:
    1. Error occurred while getting C means A and B need to be released.
  4. Return error to caller.
0 Kudos
Message 9 of 21
(1,837 Views)

AQ, haven't you missed cleaning up the ancestors' references (when those ancestors didn't throw the error)?

0 Kudos
Message 10 of 21
(1,828 Views)