LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

What Execution System does LabVIEW use with VI server?

Solved!
Go to solution

Hello All,

I've used queue-driven state machines in LabVIEW successfully for decades, part of the beauty being that I can assign them to a non-UI Execution System and then there's no interference. Recently, a colleague of mine designed a LabVIEW-based app that removed all QDSMs from the data acquisition subsystem (DAQ runs continuously for this app). Instead, he intended to rely on a different QDSM that we had developed specifically for the purpose of scheduling future events. To provide a generic interface, this Scheduler QDSM uses VI server to programmatically execute the scheduled code. The intention was to schedule the PXI measurement read operations ~once/second. Each read operation would schedule the next read operation.

That developer is no longer with the group, so I have inherited the app. I expected that, since the Scheduler QDSM was assigned to operate in the "Other 2" Execution System, so would any code that it launches programmatically using VI Server. Observe that any statically-linked code configured for "Same as Caller" Execution System would execute in Other 2. I tried assigning the called code to both "Same as Caller" and "Other 2", but had the same failed results described below.

In practice the entire system blows up. If I start data acquisition the scheduling works correctly; data are acquired regularly and I can see the measurements on front panel charts. However, if I exercise any of the front panel UI, specifically the runtime menu of the app or individual controls/indicators, I observe that DAQ stops (I probed under the hood) and charts stop updating immediately. If I hold the runtime menu activation longer than the DAQ double buffer length is configured, I get a fatal DAQ error (as expected if read measurement operations are stopped by this operation for long enough to overwrite the DAQmx circular buffer) and DAQ shuts down. This is the opposite of the non-interference I have experienced for so long.

Based on the above and some web searching, I have the impression that VI server executes (or "traverses") the UI Execution System even if the caller and callee are both configured for "Other 2" Execution System.

Can anyone shed any further light on this topic? If my conclusion above is accurate, I'm going to have to redesign this app and we are well into the integration phase. Thanks in advance.

 

Google search results include ActiveX information which isn't technically relevant, but implies use of UI Execution System.

 

Normally I'd share the offending/questionable code, but in this case it is the interaction of 2 subsystems, and I can't include the entire application. So here are pix of the scheduler code and configuration. Pretty simple.

 

Execute Scheduled VI Code.png

ASU Execution Settings.png

 

0 Kudos
Message 1 of 10
(798 Views)
Solution
Accepted by LabVU_Dog

Just guessing here, but according to the link below the Run VI method runs in the Root  loop which may be the cause of your issue.

 

http://www.labviewcraftsmen.com/blog/the-root-loop

Message 2 of 10
(792 Views)

I never had to change the preferred execution system to prevent things from 'blowing up'.

 

There was a time I thought I had to, but things blew up 😁.

 

AFAIK, There rarely is a need to change this, except for rare .net methods and maybe CLFN that require thread fiddling or 'block' the current thread.

 

Are you sure it's the preferred execution system that 'blows things up'?

 

Without seeing any code, I'd put my bet on VI(s) that are not reentrant or (functional) global(s). The VI priority doesn't help for that.

 

You might try a Call By Reference\And Forget\And Collect instead of the run method. Those call the VI dynamically as if it's a subVI, and I think it should use the execution system of the caller (if preferred execution system is same as caller).

 

The setting is the preferred execution system. AFAIK, there's no (easy) way to know what execution system is actually used...

0 Kudos
Message 3 of 10
(780 Views)

@mcduff wrote:

Just guessing here, but according to the link below the Run VI method runs in the Root  loop which may be the cause of your issue.

 

http://www.labviewcraftsmen.com/blog/the-root-loop


Good one.

 

The dreaded root loop...

 

IIRC, CBR\CAF\CAC move this 'blockage' to the open VI reference.

 

I spend (relatively) lots of time in preventing dynamic VIs for these reasons. They look like a solution, but often make life harder... Of course it can't be prevented iff you don't know the maximum number of dynamic VIs and\or don't have the VIs at build time. But other than that you don't need dynamic VIs, but they can be convenient until you run into debugging\root loop\'lost' clone issues.

0 Kudos
Message 4 of 10
(774 Views)

Thanks so much for the link to the LabVIEW Craftsman! This looks to be exactly my issue:

LabVU_Dog_0-1745507469821.png

 

 

Now that I know what the problem is, it will be easier to build an alternative.

0 Kudos
Message 5 of 10
(765 Views)

@LabVU_Dog wrote:

Thanks so much for the link to the LabVIEW Craftsman! This looks to be exactly my issue:

LabVU_Dog_0-1745507469821.png

 

 

Now that I know what the problem is, it will be easier to build an alternative.


A possible quick fix to try:

  1. Add the following key to your LabVIEW ini file 
    1. showRunAtAnyLoopMenuItem=True
    2. Need to restart LabVIEW
  2. Use the Call and Forget Method to Run VI instead of Run VI Invoke Node
    1. Right Click the Node and Choose Run At Any Loop

See https://lavag.org/topic/23800-dynamic-calling/Dynamic Calling - LabVIEW General - LAVA

 

mcduff_0-1745508475788.png

 

Message 6 of 10
(749 Views)

The Open VI Refnum and Run VI methods indeed synchronize with the root loop (one step further than just enforcing a switch to the UI Thread), for stability reasons. Especially the Open VI method touches global data structures that maintain what VIs are loaded into memory and there is absolutely no way this may ever be accessed by anything else in LabVIEW while this information is modified, without risking horrible effects for the whole LabVIEW process. The root loop is the only truly safe mutex that guarantees that. Run VI internally also has to touch this structure, so has the same problem. And in some versions of LabVIEW at least, and potentially still until the day of today, the option to execute Open VI in any thread has a small window of opportunity to crash LabVIEW at some point due to this. It may not happen for months, but might suddenly after you deployed the whole setup to a research station at the South Pole, where you need to make a trip of several weeks before you can debug the whole thing. 😁

 

Using Open VI once and then "Invoke and Forget", especially for clones, is the best way to alleviate that pain. If you have only one or very few template VIs you want to clone like that you are pretty much done with that. If however you plan on implementing something like an Actor framework, or queued message handler framework where each class can have its own internal "engine", "actor" or whatever you like to call it, things get more tricky as each actor template has to be opened once and if you need to do that for 100ds of different classes this can lead to excessive load times for your actor hierarchy. Thanks to the legendary Aristos Queue and his Actor Framework, there is a neat little trick in there where he purposefully leaks a single VI refnum that gets never closed, to minimise that cost extremely. In a project, not Actor Framework related, but with a class hierarchy spanning several hundred classes that each had its own "Processor" inheriting from the base class, this reduced the load time of the whole hierarchy from several 10s of seconds to way under one second.

Rolf Kalbermatter
My Blog
Message 7 of 10
(594 Views)

There's also this property:

wiebeCARYA_0-1745581653973.png

It can, when used properly, move VI allocation time to a time it suits you.

 

To me this still feels like moving things to the wrong side on the simplicity scale...

Message 8 of 10
(562 Views)

@rolfk wrote:

 And in some versions of LabVIEW at least, and potentially still until the day of today, the option to execute Open VI in any thread has a small window of opportunity to crash LabVIEW at some point due to this.


Out of curiosity, since you know more about the internals of Windows and LabVIEW than anyone on this forum along with possibly being a former NI employee, ...

 

Why would NI include an option that may crash their program? That seems like an odd feature to include. I guess that is why it is hidden since it is not ready for prime time. Maybe they are still testing it? But from your statement, it seems like an impossible endeavor.

0 Kudos
Message 9 of 10
(491 Views)

@mcduff wrote:

@rolfk wrote:

 And in some versions of LabVIEW at least, and potentially still until the day of today, the option to execute Open VI in any thread has a small window of opportunity to crash LabVIEW at some point due to this.


Why would NI include an option that may crash their program? That seems like an odd feature to include. I guess that is why it is hidden since it is not ready for prime time. Maybe they are still testing it? But from your statement, it seems like an impossible endeavor.


There are many options in LabVIEW that are basically experimental or pre-release quality and hidden by an ini token. Software development is an iterative process. You may start implementing something, sometimes with the intention to release it and sometimes more as an experimental feature. Truly experimental features are usually added in such a way that they only get included in debug builds but not in the release build, while features intended for release are often hidden behind a configuration token until deemed ready for prime time release.

And sometimes a developer goes in and adds a quick fix that seems to address a pain point of some other department within NI but there is no budget or time to go through the whole notion of testing, fixing, testing, fixing again, testing and testing again before it can be added into the official release.

 

Potential race conditions are extra nasty to test. The fact that a certain test setup doesn't crash anymore for a month is no guarantee that there is not still a window of opportunity to crash anyhow. The only true proof is painstaking code analysis of every single possible code path involved to assess that all code accesses to a specific shared resource are either atomic in nature or protected through a proper mutex (semaphore). And that that mutex under no condition can ever result into a mutual exclusion lock with another mutex somewhere else.

 

Non-atomic access to such a shared resource results in a crash sooner or later, mutual exclusion locks result in an application that literally hangs itself up waiting for something that never can happen. It's not impossible to proof but can get extremely tedious in more complicated situations. And that is the fate of such a feature, added for some reason at some point, maybe a developer saw a quick fix but the reviewer or manager asked: "How can you proof that this is the whole fix? And what are the implications of existing code using this function when this new feature is enabled?"  "Sorry I can't without a two weeks analysis of the whole code." "In that case we can't release it, we do not have two weeks time over. This here is the next feature you should have started working on last week already!"

 

This feature MAY work as expected since I don't know how many versions of LabVIEW. It was obviously deemed safe enough to not make it conditional disabled for a release build, but nobody so far felt like spending the not insignificant time to properly proof that it is the right fix and it is safe to enable for any LabVIEW user, no matter what their expertise in these matters is. Or it was simply forgotten although if someone had gone through the effort to fully and properly test this and make sure it is safe, I'm pretty convinced they would have added it as an official feature in the release notes and removed the ini file token.

Yes it is not ideal, but hey, ideal solutions only exist in fairy tales. 😁

 

Rolf Kalbermatter
My Blog
Message 10 of 10
(76 Views)