LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Fully release buffers acquired by an external DLL

Hello all,

 

I've run into this a couple of times - very frustrating.

 

When calling a DLL (in this case a driver DLL for a USB Spectrometer) in the development environment (i.e. A normal VI running in LV) if I *initialize - use - close* the device by way of the DLL functions LV does not actually fully release the resource.

 

For example: if you run the VI once, stop it appropriately, then try to run it again the device doesn't respond.  

 

You must completely leave LV and then restart in order to do the *initialize - use - close* routine again.

 

Alternatively you can skip the "close" function and run multiple times in a row but this probably leave some allocated buffer and/or reference hanging somewhere which is less than ideal.

 

Finally the best usage may be to create an action-engine type driver that you open once then call to your hearts content until you want to fully exit LV anyway.

 

**There must be a better solution. This behavior is not apparent in deployed executables and the companies' whose devices I have run into this with blame LV solely, claiming "no other language has this problem!"

 

Is there a way to force LV to fully "let go" when I want it to without having to shut down?

 

If you have any thoughts please let me know.

 

Cheers,

 

 

- Jolt
0 Kudos
Message 1 of 7
(4,039 Views)

When the dll is unloaded (LV is closed), the finalize section is called. So this is actually an issue with the dll, which you just don't notice in other developement enviornments and also not in a build exe.

I'm not aware of any better approach as those you suggested.

 

Felix

0 Kudos
Message 2 of 7
(4,034 Views)

I fully agree with Felix. It may be more aparent when used in LabVIEW but it is either a problem with the DLL doing STUPID things and not properly clearing up on the close() function or in how you call that DLL and don't understand how it's supposed to be used.

 

If it is something in the DLL, there is no way to solve that in LabVIEW. You could of course use the possibility to load and unload the DLL dynamically (though you would have to do it explicitedly with LoadLibrary() and FreeLibrary() since the dynamic option by providing a path name to the Call Library Node doesn't work in the way that would be needed to do this) but most likely this will not help, unless they included some extra clean up in the PROCESS_DEATTACH call of the DLLMain() routine.

 

More likely the already allocated resources will stay allocated as Windows only does resource cleanup on process exit, which of course an executable will do if you close it, but LabVIEW as development environment only unloads the VIs and stays in memory if not shutdown explicitedly so the automatic Windows resource cleanup is not triggered even if the DLL itself is unloaded.

 

So tell those driver manufacturers that not having problems in other environments is not any guarantee that they are doing things right but their defense only proofs that they really do not understand a lot about the problem and probably should have hired someone to write that driver who understands how it should be done.

Message Edited by rolfk on 05-30-2010 08:50 PM
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 3 of 7
(4,005 Views)

Does any one find a solution for it now? I ran into the same situation today. I call an external DLL in labview. When it exit for exeption, the dll file along with some related resource are locked. I can not find a function to kill the dll process in labview. I have to close the labview. It takes me long time to restart. My customer complained a lot. I plan to find a way to kill the process with windows API.

 

-Kayaoo

0 Kudos
Message 4 of 7
(3,773 Views)

Hi Kayaoo,

 

As noted by Felix and Rolf, the memory resource release problem lies within the dll itself and needs to be properly closed internally in the dll. You can refer to this LabWindows/CVI knowledgebase (http://zone.ni.com/reference/en-XX/help/370051T-01/cvi/programmerref/releasingresources/) for best practices as far as releasing resources when a dll unloads. However, I'm not sure this is the same issue as the original post given that was a memory release issue, and it sounds like you have a resource permission issue. You may want to create a new thread with more information about the external dll you are calling and then we can try to determine if the problem is from the DLL or LabVIEW itself.


Regards

Doug W

Applications Engineer
National Instruments
0 Kudos
Message 5 of 7
(3,752 Views)

I regards to my peers I respectfully disagree.  I have run into this multiple times in LabVIEW and it is indeed unique to the way LabVIEW handles things on the back end.

Other languages (such as C) will only load the DLL when the LoadLibrary line is actually called.  If the line is not called the DLL will never load.

LabVIEW however loads all DLLs when the application is started (and unloads only at exit) regardless of how your code is structured.

 

There is a work around mentioned on NI.com (see link below) but its use is impracticle.  The example in of itself does work but it fails to mention you have to do that for every exported function you call also.

http://digital.ni.com/public.nsf/allkb/77594203D78D12278625729100758BE5

 

As far as I know the only work around is to call into the Windows API directly and use LoadLibrary and FreeLibrary directly.

0 Kudos
Message 6 of 7
(3,745 Views)

DLLs doing anything else but initializing global state on load, and freeing any allocated resources on unload are basically broken. And Microsoft even goes so far as to say that you should never even attempt to release OS resources and especially unload dependant libraries in PROCESS_DEATTACH, UNLESS DllMain was called by an explicit call to FreeLibrary() which is indicated by a NULL value passed in through the "lpReserved" parameter of DllMain().

 

The reason is that while unloading a process and calling the DllMain() function of all the dependant libraries, Windows holds a global lock to many resources that could end up in a deadlock situation when calling functions like FreeLibrary() and other resource unloading functions during that.

 

Also normally only delay loaded DLLs are loaded at the first call to a function in it and that is normally a feature of the import library that comes with the DLL. However delay loaded DLLs are never unloaded once they were loaded until the module having loaded them unloads itself, and also only if no other module in the current process has still a reference to that library open. By default, import libraries will cause to load the DLL at the time the module referencing them is loaded.

 

So a scheme that relies on explicit LoadLibrary() and FreeLibrary() calls between calls to the library is not really incompatible with LabVIEW but simply requires the same procedure as it does when calling that DLL in other enviroments where you have to call LoadLibrary() and FreeLibrary() also explicitedly in your code. But such DLLs are really a monster to deal with especially during applicaton development and I would generally consider them broken.

 

If a library needs at mutiple times explicit initialization, and/or deinitialization putting that into the PROCESS_ATTACH is completely wrong. Instead the library should export explicit initialize() and uninitialize() functions for an application to call. PROCESS_ATTACH should only handle global state initialization, and PROCESS_DEATTACH can be used to clean up internal resources but should never call FreeLibrary() or similar functions when the lpReserved parameter  is not NULL. Both PROCESS_ATTACH and PROCESS_DEATTACH should do NOTHING that is required to execute to make the DLL run between multiple uses.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 7 of 7
(3,723 Views)