08-15-2023 07:43 AM - edited 08-15-2023 07:57 AM
Actually it's possible to get if it's terminating or not. But if I'm correct the info needed here is if an instrument has been initialized or not which is not the same thing.
Another possibility would be to check the step result of each setup step and use it as a precondition for cleanup steps.
But as I said, I never saw a single sequence with these kind of extra work.
08-15-2023 08:13 AM
@PragmaTest wrote:
Actually it's possible to get if it's terminating or not. But if I'm correct the info needed here is if an instrument has been initialized or not which is not the same thing.
Another possibility would be to check the step result of each setup step and use it as a precondition for cleanup steps.
But as I said, I never saw a single sequence with these kind of extra work.
OK then the coffee is working and I am tracking.
I've never seen that extra work in a Cleanup Sequence either. But, I would change the Sequence before standardizing on a change to LabVIEW Step prototype error out functionality.
Should I break out this side discussion to a separate thread for you?
08-15-2023 08:24 AM - edited 08-15-2023 08:28 AM
@PragmaTest wrote:
Actually it's possible to get if it's terminating or not. But if I'm correct the info needed here is if an instrument has been initialized or not which is not the same thing.
Another possibility would be to check the step result of each setup step and use it as a precondition for cleanup steps.
But as I said, I never saw a single sequence with these kind of extra work.
You are right on track there: You could have a precondition on 'Close Instrument A' that checked if 'Open Instrument A' had been run, but that can fail if Open did run but wasn't succesful in opening the instrument (then you needn't perform a Close). Best would be to have a table somewhere that a succesful Open noted a "Instrument A: Open" state in. Then have Close check that state, and update it after its succesful close to "Instrument A: Closed". Such a lookup can be made in multiple different ways in TestStand: TS variables of different kinds, a LabVIEW FG, a database, or other kinds of deterministic state data.
We always do stuff like that (also in TS sequences). There are many ways to be 99% sure of state, but to be 100% sure your state transaction scheme need to be existing and atomic to work and to counter racing.
"Pugnacious ", that's not quite an insult, but close 😂 Rather that than being smacked in the face because my stuff broke a factory with me being 1000 miles away...
08-15-2023 08:36 AM
@JÞB a écrit :
@PragmaTest wrote:
Actually it's possible to get if it's terminating or not. But if I'm correct the info needed here is if an instrument has been initialized or not which is not the same thing.
Another possibility would be to check the step result of each setup step and use it as a precondition for cleanup steps.
But as I said, I never saw a single sequence with these kind of extra work.
OK then the coffee is working and I am tracking.
I've never seen that extra work in a Cleanup Sequence either. But, I would change the Sequence before standardizing on a change to LabVIEW Step prototype error out functionality.
Should I break out this side discussion to a separate thread for you?
I don't change the LV step prototype error, I just enable Ignore Run-Time Error and all cleanup steps (LV or not).
Thanks, but I think it's interesting to keep the TS cleanup topic closed to this LV error handling topic.
08-15-2023 08:38 AM
@SteenSchmidt wrote:
@PragmaTest wrote:
As concluded before, my habit comes from TestStand Terminate + cleanup steps.
Consider this example :
SETUP
Open instrument A
Open instrument B
Open instrument C
MAIN
Action instrument A
Action instrument B
Action instrument C
CLEANUP
Close instrument A
Close instrument B
Close instrument C
If Terminate is pressed while opening instrument A, a jump is done to cleanup group, then instrument A is closed, but instrument B and C output an error since they are not opened.
I want the Terminate button available for every user, I want the TS error pop-up enabled, but I don't want the error pop-up displayed in the previous scenario while terminating.
In TestStand there is no such thing as error input parameter.
In TestStand there is a step option called Ignore Run-Time Error.
That's why I activate this option on cleanup steps and it never ever gave me a single side effect.
But, I can understand that is not easily transposable in LabVIEW, since LV has an error data flow mechanism, no error callback mechanism and no native cleanup jump mechanism.
Your problem is basically that you have too little intelligence in your TestStand Close procedures, and are taking a shortcut instead of completing your code. You are asking 'Close Instrument B' and 'Close Instrument C' to close instruments that haven't been opened. They must error out in this case, it's not the correct action to suppress their error messages. What when they can't close instruments that are actually opened?
What you should do is only close what you have opened, and then be happy about your functions returning errors when they can't do what you have asked of them.
Either improve your setup/cleanup logic in the sequence, or build more context awareness into your instrument management software.
A mature software developer has realized that creating software is a lot of tedious work. The "creative" part is fun, architecting the sunshine scenario. The tough part comes when you have to make all the failure modes also work. Like a painter needing to mask off, finish with clear coat, and clean their tools. If you don't do it, the fun part quickly stops being fun.
This is universal, it has nothing to do with programming/scripting language: Every function must do exactly what it advertizes, and it must tell you if it failed. No hidden side effects. This takes a lot of stamina to pull off, and not everybody can muster that. That's why so much software fails when you look around you on everyday things. Destinguish yourself from the crowd: Strive to be a great programmer.
Steen, I think you are adding a lot of complexity for little or no value.
"What when they can't close instruments that are actually opened?"
- What scenarios would cause this to actually happen?
- What or the negative consequences if this were to happen?
- What can you actually do about it at that point in the program?
Obviously you can always log it and alert the user, but that can quickly become noise. If there is a real problem, it should show up somewhere else. In that case I guess the logging might be useful in telling you the instrument didn't close properly, but you've probably already figured that out.
08-15-2023 08:39 AM
@SteenSchmidt a écrit :
@PragmaTest wrote:
Actually it's possible to get if it's terminating or not. But if I'm correct the info needed here is if an instrument has been initialized or not which is not the same thing.
Another possibility would be to check the step result of each setup step and use it as a precondition for cleanup steps.
But as I said, I never saw a single sequence with these kind of extra work.
You are right on track there: You could have a precondition on 'Close Instrument A' that checked if 'Open Instrument A' had been run, but that can fail if Open did run but wasn't succesful in opening the instrument (then you needn't perform a Close). Best would be to have a table somewhere that a succesful Open noted a "Instrument A: Open" state in. Then have Close check that state, and update it after its succesful close to "Instrument A: Closed". Such a lookup can be made in multiple different ways in TestStand: TS variables of different kinds, a LabVIEW FG, a database, or other kinds of deterministic state data.
We always do stuff like that (also in TS sequences). There are many ways to be 99% sure of state, but to be 100% sure your state transaction scheme need to be existing and atomic to work and to counter racing.
"Pugnacious ", that's not quite an insult, but close 😂 Rather that than being smacked in the face because my stuff broke a factory with me being 1000 miles away...
Pugnacious is not an insult, at least in french 🙂 . It's quite close to a compliment in my opinion.
08-15-2023 09:09 AM - edited 08-15-2023 09:10 AM
@Taggart wrote:
@SteenSchmidt wrote:
@PragmaTest wrote:
As concluded before, my habit comes from TestStand Terminate + cleanup steps.
Consider this example :
SETUP
Open instrument A
Open instrument B
Open instrument C
MAIN
Action instrument A
Action instrument B
Action instrument C
CLEANUP
Close instrument A
Close instrument B
Close instrument C
If Terminate is pressed while opening instrument A, a jump is done to cleanup group, then instrument A is closed, but instrument B and C output an error since they are not opened.
I want the Terminate button available for every user, I want the TS error pop-up enabled, but I don't want the error pop-up displayed in the previous scenario while terminating.
In TestStand there is no such thing as error input parameter.
In TestStand there is a step option called Ignore Run-Time Error.
That's why I activate this option on cleanup steps and it never ever gave me a single side effect.
But, I can understand that is not easily transposable in LabVIEW, since LV has an error data flow mechanism, no error callback mechanism and no native cleanup jump mechanism.
Your problem is basically that you have too little intelligence in your TestStand Close procedures, and are taking a shortcut instead of completing your code. You are asking 'Close Instrument B' and 'Close Instrument C' to close instruments that haven't been opened. They must error out in this case, it's not the correct action to suppress their error messages. What when they can't close instruments that are actually opened?
What you should do is only close what you have opened, and then be happy about your functions returning errors when they can't do what you have asked of them.
Either improve your setup/cleanup logic in the sequence, or build more context awareness into your instrument management software.
A mature software developer has realized that creating software is a lot of tedious work. The "creative" part is fun, architecting the sunshine scenario. The tough part comes when you have to make all the failure modes also work. Like a painter needing to mask off, finish with clear coat, and clean their tools. If you don't do it, the fun part quickly stops being fun.
This is universal, it has nothing to do with programming/scripting language: Every function must do exactly what it advertizes, and it must tell you if it failed. No hidden side effects. This takes a lot of stamina to pull off, and not everybody can muster that. That's why so much software fails when you look around you on everyday things. Destinguish yourself from the crowd: Strive to be a great programmer.
Steen, I think you are adding a lot of complexity for little or no value.
"What when they can't close instruments that are actually opened?"
- What scenarios would cause this to actually happen?- What or the negative consequences if this were to happen?
- What can you actually do about it at that point in the program?
Obviously you can always log it and alert the user, but that can quickly become noise. If there is a real problem, it should show up somewhere else. In that case I guess the logging might be useful in telling you the instrument didn't close properly, but you've probably already figured that out.
You might think I'm in the minority here, but there are probably many people on here who use Actor Framework. (Note: I'm not huge on AF, but I've used it.)
In AF you have the Stop Core method that gets called whenever the actor stops. The actor can be in any state when it stops. The actor private data may contain a lot of references. Many are opened in prelaunch init when the actor starts, but some of them may be transient. So when the actor stops you have no idea if any of the references are open or not, the goal is simply to make sure they are all closed to prevent memory leaks. No one keeps track of which ones are open and only closes those. Common practice is to close them all and ignore the errors. Adding code to check all that and handle the errors from closing things that were possibly never even opened is completely unnecessary and gives the potential of screwing up that logic and leaving the reference open.
08-15-2023 09:51 AM
@Taggart wrote:
Steen, I think you are adding a lot of complexity for little or no value.
"What when they can't close instruments that are actually opened?"
- What scenarios would cause this to actually happen?
Have you in all honesty never seen a Close fail on a busy instrument, leaving that instrument's ID and other resources unavailable for your next use?
This complexity is real. Remember, we're not necessarily talking about merely closing a reference anymore, but in fact 'Close Instrument B' in its entirety. If that Close doesn't complete succesfully, or even didn't manage to release a reference, you may not be able to communicate with that instrument again or use any of the resouces that instrument is currently holding on to. This problem could range from a nuisance wasting time or confusing the operator, to physical damages costing a lot of money or be a safety issue.
- What can you actually do about it at that point in the program?
Obviously you can always log it and alert the user, but that can quickly become noise. If there is a real problem, it should show up somewhere else. In that case I guess the logging might be useful in telling you the instrument didn't close properly, but you've probably already figured that out.
You shouldn't be doing anything about it at that point in the program, other than perhaps wait a little and try again before eventually failing outright (if you want to retry depends on your experience with if that will help in the situation). But what should happen is the same as with all errors: They cascade downstream until it reaches a level that can do something about it. For errors that no level in the system can fix, it'll end up at a human being that can make the proper reparations ("Restart computer", "Patch SW" or similar). But it shouldn't be hidden deep in your application and cause all sorts of side effects that make you believe something else is amiss.
Is a hardware malfunction or poorly designed software causing all sorts of side effects "noise"?
I'm constantly reminded why stuff around us doesn't work as expected.
08-15-2023 09:52 AM
@SteenSchmidt wrote:
@PragmaTest wrote:
The suggestion to add a precondition is exactly the same thing as testing the validity of the refnum in the ini file challenge.
As far I see nobody's has done it in the screenshots, nor NI in the close ini file function.
Testing the refnum is the wrong way around. You should operate from deterministic certainty that you need to close the refnum or not: If you know that the refnum was newer opened, don't attempt closing it. If you know the refnum was opened, then attempt closing it. Live with the consequences of either action. If you test the refnum, then you'd miss the problem with somebody else having prematurely closed it.
It's a racing condition testing the refnum anyways: Someone might close it just after you're tested it, but before you attempt closing it. You'll hit an error anyways. Eliminate the racing condition by just closing the refnum and see what happens.
Either way of handling is appropriate assuming the designer is aware of the limitations and corner cases and either doesn't care about the details or takes care (code-wise or design-wise) that it's essentially irrelevant.
Any question with the word "Style" in it is always going to be somewhat controversial. I'm so grateful that there are different styles out there. The only styles that are not OK are the ones done out of ignorance. Everything else, as long as the consequences are known, controlled or have been demed safe to ignore, is fine (theoretically at least). Depends on where your focus is.
08-15-2023 10:10 AM
@Taggart wrote:
In AF you have the Stop Core method that gets called whenever the actor stops. The actor can be in any state when it stops. The actor private data may contain a lot of references. Many are opened in prelaunch init when the actor starts, but some of them may be transient. So when the actor stops you have no idea if any of the references are open or not, the goal is simply to make sure they are all closed to prevent memory leaks. No one keeps track of which ones are open and only closes those. Common practice is to close them all and ignore the errors. Adding code to check all that and handle the errors from closing things that were possibly never even opened is completely unnecessary and gives the potential of screwing up that logic and leaving the reference open.
I don't care much about "common practice". There are plenty of blissfully ignorant programmers out there, that don't think too deep about the Why but who have just learned a bunch of Hows. Stop Core's job is to stop the actor core, period. When the actor is stopped one pleasant side effect is that you have no memory leaks. Another pleasant side effect should be that you know positively that it was stopped in a safe and predictable way, and if not your parent actor will be notified that you stopped with an error. Nowhere does it say that Stop Core's job is to close all references without thinking.
Your example illustrates perfectly my worry about thinking this way: Actors are differerent. If you always implement Stop Core following the pattern: "Identify all references, close them all, pass no errors", then you are templating without thinking. Yes, often times Stop Core should clean up your own references that are no longer to be used. Often those references can just be closed without looking at their current validity *but that can only be determined by you, because you have contemplated the consequence of each Close*. In some rarer cases you need to do much more, and in those situations your actor better have provisions to track lifetime and state of important bits, to be able to take the proper action in all scenarios when it stops. You only have a chance of identifying those situations if you in fact consider what you do each time.
Again, I must point out that I'm not saying you should double check every bit in your code with even more code. A lot of what I'm talking about you are probably doing all the time yourself, perhaps just not considering it very consciuosly. But I'll kick anybody that walks up to me and says they *always* do a silent close. Never *always* do something, think about the context you are in NOW.