LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
drjdpowell

Means to register a DVR-cleanup callback fior use when DVR released when VI goes idle.

Status: New

DVRs are references, and are automatically released when the VI hierarchy that created and "owns" it goes idle (stops executing).  Commonly, the DVR just contains by-value objects, or LabVIEW references that are also automatically released, but an important use case of DVRs is wrapping a non-labview reference that must be properly cleaned-up.   An example is an SQLite Connection pointer that must have a dll method called on it in order to release the database file it is holding open.  Many dlls have similar pointers/handles that need to be properly closed.  This is a headache for Programmers, who cannot rely on a stopped VI releasing its resources, often requiring restarts of LabVIEW to unload the dll.

 

A clean and easy solution to this problem would be to allow a "DVR Cleanup Callback VI" to be registered with the system when the DVR is created.   That VI would be called if and only if the DVR is release because its calling VI hierarchy goes idle.   This VI would contain the code to cleanup/close the contained non-LabVIEW references.  Could have other uses, such as debugging. 

 

I have developed multiple APIs that wrap non-LabVIEW dlls, and this feature would be a very significant help.   Please consider it.

18 Comments
wiebe@CARYA
Knight of NI

More options, more power. +1

AristosQueue (NI)
NI Employee (retired)

Existing functionality: The callback behavior exists already on DLLs. For the third-party references, you can fill in the "Callbacks" tab of the Call Library Node to specify cleanup of those references. This may suffice for many of your use cases.

 

You're asking for something similar for DVRs. It's a reasonable request. I'll add my kudos.

drjdpowell
Trusted Enthusiast

Is that the same thing, AQ? Is the "Unreserve" callback fired when the top-level VI goes idle?  Sounds like it is when the subVI is unreserved, which is only when all calling top-level VIs have stopped.  That would be bad for actor-like async-calling architectures.

 

Also, that way is extremely difficult, requiring a sophisticated custom C dll to call the main dll.  This idea would be orders of magnitude easier to use.

AristosQueue (NI)
NI Employee (retired)

I didn't say the DLL approach was easy. Merely that it existed as a workaround and was intended to address this use case. I definitely agree the G version would be simpler.

 

As for how it works, you have all the documentation I have. If it isn't clear, we'll have to ping around for someone who knows it better.

wiebe@CARYA
Knight of NI

How about a general (user) event that triggers when a VI's top level VI goes idle?

 

I think we could already do that, but it's a hassle.

Spoiler
(maybe something like: register a queue, start dynamic VI that waits for the queue to become invalid, send some event, taking care that the event registration itself isn't invalidated, etc.).

A more practical way would provide solutions for registered DVRs, DLLs, etc..

 

Adding some registration to everything that's by reference seems a lot of work, and attaching it to the top level VI itself seems a lot easier? And just as good?

 

 

drjdpowell
Trusted Enthusiast

I think we could already do that, but it's a hassle.

 

I've done that.  It's how subactors in Messenger Library receive an "Autoshutdown" message when their calling actor stops for any reason.  But it was only simple for me because I was leveraging the existing "Async Action" code in Messenger Library.  I can't make independent libraries depend on Messenger Library.   Even with Messenger Library, the described idea would be simpler.

 

>How about a general (user) event that triggers when a VI's top level VI goes idle?

>Adding some registration to everything that's by reference seems a lot of work,

>and attaching it to the top level VI itself seems a lot easier? And just as good?

 

That sounds a lot MORE complicated to me.  Who's listening to this User Event?  How does whatever it is get the DVR reference.  I'm imagining providing a callback VI with a DVR input and the cleanup code inside it, provided as input to a new "Create DVR with Cleanup Callback" primitive.  Very simple.

 

 

wiebe@CARYA
Knight of NI

Sorry about that. I see now why the callback mechanism is (also) useful.

 

 

My first impression was that a function that attached a callback to a DVR was suggested, and then maybe add a similar function to other references. I know that is just my interpretation.

 

So we are looking for a function that accepts any reference, and calls a callback when the top level VI goes idle, right?

 

Or (why not), a function that calls a callback when the top level VI goes idle, and allows anything (including references) as input. Anything could be references, clusters of references, variants, etc..

 

Would this callback be called before the reference is invalidated? Or just as a notification that it was invalidated?

drjdpowell
Trusted Enthusiast

So we are looking for a function that accepts any reference,

> and calls a callback when the top level VI goes idle, right?

 

Uh, No.  I may not be explaining it well.   I want to ensure that clean-up code is executed on the contents of a DVR just before the DVR is invalidated by the calling VI hierarchy going idle.   Specifically, I'm thinking about pointer/handles from some dll that need functions called to close them properly, but one could do other things (my "Autoshutdown" messages would be much easier, and lower overhead, to implement, for example).  This allows one to make wrapper libraries about dlls that behave the same as LabVIEW references, in that they are cleaned up when the VI goes idle.

 

I don't particularly care about any other LabVIEW references.  Adding this feature to DVRs is the major benefit. 

 

>Would this callback be called before the reference is invalidated?

 

Actually, the best thing would be to have the DVR released and the callback passed the by-value contents of DVR.  That eliminates any race condition with other code also trying to release the DVR.

 

 

AristosQueue (NI)
NI Employee (retired)

So, there is one big problem with the callback mechanism. I was reminded of this by someone more senior who has worked on LV way longer than I have... apparently, this idea has been proposed before. It floundered on one question: what do you do about the Abort button?

 

When debugging, should the Abort button trigger the callback VI or not? It's a bit weird to have an Abort button that doesn't abort the whole application. But at the same time, it's a bit weird to have a cleanup proc that you can't rely upon to always cleanup and leave your system in a clean state.

 

Should clicking the Abort button throw a dialog that asks "Run cleanup VIs?" Even if the dialog only appears when someone has registered some cleanup VIs, that seems awkward. And the scripting Abort method would need an input for whether to abort or not... and how would an editor plug-in tool designed to abort VIs know whether a given VI needs its cleanup VIs to run or not? Messy.

 

If the cleanup VIs always run when aborted then how do you abort the (likely-running-in-the-background-without-their-panels-open) cleanup VIs themselves? Double click the abort button?

 

"Didn't LV solve this with XControls?" says I. After all, the whole "change from run mode to edit mode" routine runs in response to an abort, right? True, but those don't need refnum data whose life time is tied to the application being aborted. The XControls are essentially independent apps from the main app. And they do have a problem with being aborted, but because of the (awkward-and-often-frustrating) way that the Facade VI is structured, it rarely goes into an infinite loop. And your other methods aren't usually doing much system damage in an XControl. But if the callback is for a hardware refnum, we really need to make sure the 20 bijillion megawatt laser goes into a safe mode when you hit the Abort button. OK, maybe you shouldn't be hitting the Abort button for that kind of hardware. But you get my point, I hope. Either you can rely upon the clean up or you cannot. With all the LV built-in refnums, you can rely upon the cleanup. That's the challenge for this idea...

 

... How do we add a language thing to LabVIEW that lets you write code to shutdown an API that provides the same guarantees as the built-in cleanup procedures for refnums without introducing another layer of application debugging or with an additional layer that is straightforward to control?

 

United G programmers: Discuss!

AristosQueue (NI)
NI Employee (retired)

Powell: Weibe's question about the timing is still relevant even with your "pass the contents" fix. I have several DVRs that contain other refnums, including other DVRs. Are those refnums still valid when the cleanup VI for the outer DVR runs? If so, they have to be before LabVIEW has done the built-in cleanup. Which seems fine to me, but it is an issue that needs to be thought through.

 

Also, even if the refnum is invalidated and the contents are passed to the cleanup VI, we probably would also want to pass the refnum because those are frequently used as lookup keys in registration tables.