Actor Framework Discussions

cancel
Showing results for 
Search instead for 
Did you mean: 

Error in Pre Launch-Init override

Solved!
Go to solution

Hi everyone,

 

how do you deal with errors in Pre-Launch Init when overrides are involved?

 

According to this thread, if an error occurs in Pre-Launch Init, we should close all references before exiting because there is no explicit clean-up location in that situation. That is what I've been doing and I'm comfortable with it.

However, when overrides are involved, this can break down.

Let me illustrate with actors A and B.

 

B inherits from A and both of them open references in their respective Pre-Launch Inits. Both of them follow the recommendation to close all potentially open references in case of an error during the acquisition of said resources.

 

B calls parent method and so if the parent method is the one to return an error (Pre-Launch Init from A), then B can react accordingly and ensure no references leak out of Pre-Launch Init B.

 

What should we do in the case where Pre-Launch Init B throws the error? Pre-Launch Init A has no idea that Pre-Launch Init B failed and will not explicitly release any references.

How can this be done without relying on automatic closing of references when the actor dies shortly after?

 

Assumptions and Limitations:

- Actor A defines Pre-Launch Init as must override so I cannot call parent method conditionally.

 

The question goes beyond the use of references. Luckily, references will be closed when actor dies anyway. But what about actions we want to happen in Pre-Launch Init that don't get negated when the actor dies (such as sending a message to another actor)?

In the case where there is only one layer of Pre-Launch Init, we can make the code conditional, but it's not so simple when overrides are involved since the parent Pre-Launch Init doesn't know about the results of the child Pre-Launch Init.

 

Thanks for any feedback or suggestions on how you deal with these kinds of situations.

0 Kudos
Message 1 of 13
(4,608 Views)

I had this conversation with Allen a while ago.  The recommendation is to put the call parent node inside the no error case.  So do all your opening references and collect the errors.  In the case structure where you close those references if there is an error, move the call parent into the no error case. That way if the child has an error the parent doesn’t have to worry about cleaning up its references because it’s prelaunch init never gets called.    Hopefully that is clear.  I’m on my phone and can’t post a screenshot.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
Message 2 of 13
(4,582 Views)

Oh and this works because pre launch init is not actually “must override” as you assume.  I thought the same thing until Allen corrected me.

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 3 of 13
(4,579 Views)

I saw right after posting that there was a new slide in the training material that explains this. 

The must override comes from my own actor layer. I wanted some of the functionality of my common actor ancestor to always be run so I made it must override.

0 Kudos
Message 4 of 13
(4,576 Views)

When I talked to Allen, he mentioned he was going to update the training material.  

 

Since you want it to run all the time, not sure how best to enforce that.  Perhaps Allen or Aristos will have a good answer. 

 

Perhaps its something you could wait to do until Actor Core and just do it before the message handling (ie. call parent).

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 5 of 13
(4,572 Views)

I thought of overriding actor core as well to do it there but then i have no guarantee that it runs before any helper loops in further overrides. 

It seems that no matter where I do things, there is an issue. In a normal actor this can be solved for the local needs, but since I want this actor to be the common ancestor of all my actors, and I want it to not affect further classes more than necessary, there are many possible scenarios that can get in the way. 

0 Kudos
Message 6 of 13
(4,570 Views)

Here's a crazy thought, but it just might work...

 

Override Handle Message.vi in the parent.  Have a boolean in the parent to determine whether it is initialized or not.  If it's not, then execute your initialization code (of course make it a dynamic dispatch) there before handling the message.  That way it gets initialized before the actor handles a single message.  

 

Maybe not the most elegant (and your are taking a hit with every message, but it is just checking a boolean), but depending on your use case it might work...

 

Maybe Allen or Aristos will have a more elegant solution. 

 

Sam Taggart
CLA, CPI, CTD, LabVIEW Champion
DQMH Trusted Advisor
Read about my thoughts on Software Development at sasworkshops.com/blog
GCentral
0 Kudos
Message 7 of 13
(4,565 Views)

Interesting idea, and would certainly do the job, but it doesn't feel right to me.

 

The way I solve this right now is that I wrap the actor launcher into a launcher for my common actor and perform clean-up if it fails. It works fine for my specific use-case, but I was exploring other ideas or ways of doing that.

 

0 Kudos
Message 8 of 13
(4,555 Views)
Solution
Accepted by topic author jtagg

@jtagg wrote:

Interesting idea, and would certainly do the job, but it doesn't feel right to me.

 

The way I solve this right now is that I wrap the actor launcher into a launcher for my common actor and perform clean-up if it fails. It works fine for my specific use-case, but I was exploring other ideas or ways of doing that.

 


Doesn't feel right to me either -- I want the parent class fully initialized before I do my own initialization because one often depends upon the other. Allen's solution works for simple situations, and it is easy to implement, so I don't mind it being promulgated, but I usually end up creating something more complicated. The problem is that we didn't design Pre-Launch Init.vi well -- we considered only the straightforward without inheritance. So what I've had to do is create "Pre-Launch Init.vi" in my ancestor actor. It does the following:

  1. calls "Pre-Launch Init Core.vi", a dynamic dispatch VI marked as "Must call parent", which is what all the children override.
  2. if Core returns an error, call "Handle Pre-Launch Failure.vi", a dynamic dispatch VI marked as "Must call parent", which all the children also override.

No other children override Pre-Launch Init.vi.

 

It's annoying, but it gives better cleanup sequence. Remember that deep levels of "Handle Pre-Launch Failure.vi" might never have allocated anything in the first place, depending on where the error occurred that caused the hierarchy to stop doing the rest of Core.

0 Kudos
Message 9 of 13
(4,468 Views)

(and changing pre-launch init.vi at this point would be a significant breaking change to existing code)

0 Kudos
Message 10 of 13
(4,467 Views)