LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Improper garbage collection of queues

To whom may I address this question?

It seems to me that queues are garbage collected differently compared to other LabView data, and the choice to do this when the VI has finished executing puzzles me.

Suppose I open a reference to a VI and execute it using Invoke Node Run VI. If I create a new queue inside the VI and present its reference as an indicator, the reference will become invalid the instant the VI finished, as the queue is automatically released and garbage collected. This happens BEFORE the automatic LabView garbage collection when the VI reference is closed. If the NORMAL LabView procedure was followed, the queue would have been ''alive'' as long as the VI reference was kept open (this would be PROPER behavior).


To me, the decision to garbage collect queues when the creating VI finishes executing is IMPROPER, because it violates the BASIC PRINICPLE that an opened reference must be closed in order to release its resource (unless the programmer requests this automatic behavior).

I would like an answer from a responsible developer at National Instruments.

/Patrick
0 Kudos
Message 1 of 7
(4,449 Views)
Patrick

Which version of Labview are you using ?

For the sake of argument, I will assume you are using LV6.1 or above (Queue behaviors was changed between 6.0 and 6.1, but has remained essentially unchanged since)

As far as I know, queues references are not destroyed until you invoke the primitive "Release Queue" with force destroy set to true.

What is exactly happening to you? How do you know that the queue reference "become invalid the instant the VI finished" ? Are you passing the Queue refnum to another VI ? Are you trying to use the queue after that VI closed in another VI ? Does labview return an error ?
Are you using unnamed queue?

Please provide us with a few more information and we may figure out what's going on.

PJM

PS1: I am n
ot a working for NI
PS2: The NI specialist for queue is stephen mercer (I believe he wrote them)


  


vipm.io | jki.net

0 Kudos
Message 2 of 7
(4,448 Views)
I am using Labview 7.1.

As far as I know, queue references are destroyed when the top level VI where the queue has been created has finished executing. This is explicit in the documentation of ''Release Queue''.

To illustrate my problem, I have attached three block diagrams. In the first VI, Queue1.vi, a queue is created and passed to the caller via an indicator. The second VI, Queue2.vi, takes a queue and does something with it (it is not important that the queue is released, any queue operation would do). As long as the top level VI is executing, everything works fine. Try it! Create a VI called QueueTestStatic.vi, insert Queue1.vi and Queue2.vi, wire them together and create an error out indicator. The VI will execute and produce no error. (I could not attach more than three files).

I need to do the same thing as in QueueTestStatic.vi, but with dynamically loaded VI:s. This is illustrated in the third VI, QueueTestDynamic.vi. When it is run, Queue1.vi is executed as a top level VI. The queue reference is passed to Queue2.vi, just as it would when you wire them together. (How the reference is passed to Queue2.vi is actually irrelevant.) When Queue2.vi is executed (top level), the queue operation fails with error code 1. Conclusion: what was possible to do with static sub-VI:s, is not possible to do with dynamically loaded VI:s.

To clairify why this is upsetting, please note the following: Labview has a garbage collection routine which destroys objects when a top level VI has finished executing, and all VI references to the top level VI has been closed. Using this knowledge, it is possible to run dynamically loaded VI:s (they will run top level) and to keep the reference to the VI open to prevent the garbage collector to kill everything created in the VI. As you can see, I attempted to use this feature to preserve the queue.

But it does not work with queues. Queues does not obey the normal rules of garbage collection. Instead, they seem to be destructed the moment Queue1.vi has finished executing. As you can see in the documentation of ''Release Queue'', this behavior could also be expected. But it is wrong. In a sound programming language, each approach (static or dynamic) would work just the same, without the need to make assumptions about the loaded VI containing queues or not. (Or an object of type xyz for that matter.)

In my projct, I cannot make assumptions on the implementation of the loaded VI:s (e.g I cannot restrict the uses of language primitives) and I cannot radically change the implementation in the loaded VI:s (since they belong to other projects). What I do need is the ability to choose to execute the VI:s dynamically or statically, without this decision affecting the result of the algorithms.

As I am unable to tell you more about the project I am working on, if you fail to see the possible applications of the dynamic approach, I am truely sorry. At least I hope that I made the theoretical motivation clear. I would like the language to behave in a consistent and predictable way. Why should queues be treated differently? Why not use one mechanism for all language primitives? The only difference is a small, but important condition (the italic text above).

Oh, and did I forget to tell you that my project dropped dead the instant I discovered why the annoying error occured?

Thank you millions for trying...
/Patrick
Download All
0 Kudos
Message 3 of 7
(4,448 Views)
Heh. One of the devlopers here at NI clued me in that my name had been mentioned in a post on this thread. The queues are indeed my responsibility.

Patrick: Your question regards the queue reference opened by a VI that is itself opened through a VI reference. The proposition you offer is that the queue reference should remain valid as long as the VI reference remains valid. I think I can explain why the current behavior is consistent with our handling of all references.

Consider the VI reference itself -- ignoring the queue reference for the moment. If I run Alpha.vi and in that VI open a reference to Beta.vi, when is the reference closed? It could be closed when you encounter an explicit "Close VI Reference" node. But if this is never done, then the reference to Beta.vi will be closed when Alpha.vi stops running. The reference is garbage collected when the VI stops execution. A top-level VI is always responsible for closing anything opened during its execution.

Now the queue reference is opened during the execution of Beta.vi. If I just run Beta.vi directly (clicking on the run arrow), the queue reference will be thrown away when Beta.vi goes idle. Again, the principle is that a VI is responsible for closing anything opened during its execution.

An invocation through a VI Server reference does not change this. A VI called through the "Run VI" method or through "Call By Reference" node will clean up all its references when it stops execution.

I think that where you (or others) might contend there is some discontinuity is the fact that a subVI call and a VI Server call are not treated the same. A reference opened in a subVI call is considered part of the stuff opened by the top-level VI. The subVI's reference is not cleaned up when the subVI stops executing but rather when the top-level VI that called it stops executing. But a VI Server call is considered to be an invocation of a new top-level VI. Anything opened in the call is cleaned up when the call is finished, even though the caller may continue execution.

Should these be the same? No. A subVI call is inherently part of the top-level VI. If I abort the top-level VI, the subVI will stop execution. But if I run Alpha.vi and it opens a reference to Beta.vi and starts Beta running, aborting Alpha will not necessarily stop Beta. True, aborting Alpha will close the reference to Beta, and if this is the only reference to Beta, then Beta will indeed stop running. But Beta could as easily acquire a reference to itself, open its own front panel, or some third VI might have a reference to Beta. In these cases, Beta will continue execution even though Alpha has stopped.

In summary, every top-level VI is responsible for closing references opened during its execution by its own diagram or those of its subVIs. A VI Server invocation is an execution of a separate top-level VI. Thus a queue reference opened in a VI Server invocation should be closed as soon as that VI Server invoked VI finishes execution.

I'd also point out a slight problem with your statement of the operating principle of LV. You stated "an opened reference must be closed in order to release its resource (unless the programmer requests this automatic behavior)." This is not quite true. The automatic behavior ALWAYS applies, and the programmer may pre-empt the automatic behavior with an explicit call to Close Reference earlier than the automatic.

I hope this helps.

-- Stephen Mercer
LabVIEW R&D
Message 4 of 7
(4,448 Views)
I don't have an immediate answer, but I have encountered no such problems during my working with queues.

I'll repeat a question which has been asked before, but you've not answered.... Do you used named queues?

I find is a much better approach (theoretically and practically) to pass the name of a queue and let the sub-vi (or dynamically loaded VI, I don't want to split hairs here) and let the sub-vi acquire the queue. This way you have the error handling for an unsuccessful queue acquire built-in.

I've had projects in the past where I could run the top-level VI, spawn several parallel Vis to feed data into certain queues, stop the main VI while letting the sub-vis run in the background (filling the queues all the while) and then re-sta
rt the main VI. Doing this, I immediately see that all of the old values recorded while the main VI was stopped are in the respective queues. Of course, I use named queues.

Hope this helps

Shane.
Using LV 6.1 and 8.2.1 on W2k (SP4) and WXP (SP2)
0 Kudos
Message 5 of 7
(4,448 Views)
Having read The post below, I have to add that all my "sub-vis" are also loaded using VI server.

Shane.
Using LV 6.1 and 8.2.1 on W2k (SP4) and WXP (SP2)
0 Kudos
Message 6 of 7
(4,448 Views)
"Queues does not obey the normal rules of garbage collection."

Compare the difference between "Queue Reference" and "Queue". If I make 2 calls to "Obtain Reference" for the same named queue, check the refnums I get back. These are two different values. Each is an independent reference to the same queue. The reference is closed when the top-level VI that acquired it is closed. The queue itself is closed only when all references to that queue are closed.

I will contend that the language is consistent as long as you differentiate the reference from the object the reference is referencing. See my earlier post for the distinction between a subVI call and a VI Server invocation.

-- Stephen Mercer
LabVIEW R&D
Message 7 of 7
(4,448 Views)