04-30-2013 09:32 AM
Using NI-VISA 5.2 and 5.3, attempting to viClose a Resource Manager session when processing DLL_PROCESS_DETACH in the DLLMain function of an instrument driver DLL made in Visual Studio 2010 can cause a deadlock. This did not happen with earlier NI-VISA versions. Should it be possible to clean up any outstanding Resource Manager sessions when a DLL unloads?
05-01-2013 05:32 AM
Attached, a Visual Studio 2010 project demonstrating the deadlock.
"NI-VISA 5.3 result.txt" is the console output at deadlock (it doesn't get as far as outputting "Done!").
"VS2010 break execution.bmp" is the dialog produced (after a delay) after breaking execution.
"VS2010 output (clicked window close icon).txt" is VS2010 IDE output produced (after a delay) after program termination by clicking the console window's close icon.
05-09-2013 06:03 AM
Hi Dave,
Did this work without fail with a previous version of NI-VISA, if so which one? Would it be possible to go back to a previous version of NI-VISA as a workaround?
James
05-09-2013 06:22 AM
Hi James,
Never a problem with any version before 5.2, but it's difficult to keep asking customers to downgrade. As a workaround, re-coded to avoid calling viClose in this situation - but carries the risk of a memory leak if cards aren't explicitly closed before unloading (RM session left open).
Thanks,
Dave
05-14-2013 05:14 PM - edited 05-14-2013 05:20 PM
We found the same deadlock issue with viClose().
Ie when viClose is executed from the C++ object destrcutor of a file scope object, ie viClose(ResourceManager) when processing DLLMain's DLL_PROCESS_DETACH, which calls Microsoft's C++ runtime object cleanup code, ie calls destructors.
The deadlock issue was discovered a few weeks ago when a customer upgraded to NI-488.2 version 3.1.1. Luckily at the time, we were able to internally switch from using VISA to NI-488 via our hardware abstraction layer, and continue suporting the customer.
Today, I was able to track down the customer issue to NI-VISA 5.3 and create a work arround. ie, creating a new DLL funciton and calling it from the application before the main application calls FreeLibrary() on the DLL.
This issue doesn't happen with NI-VISA 5.2.
05-14-2013 05:18 PM
FYI, I added a call to Win32 SDK's DebugBreak() so I could attach a debugger to the destructor. I tried stepping over the viClose(), but it never returns.
05-14-2013 06:03 PM
Just to clarify, we do not install NI-VISA with an independet installer, we install it using the ni-488.2 installer. So when I say it works with NI-VISA 5.2, I am specifically talking about visa32.dll 5.2.0.49152 that installed with NI-488.2 3.1. With this version of NI-VISA, viClose does not deadlock. As far as I can tell, this was the last working version.
05-15-2013 08:53 AM
The solution you thought of is the right solution. Your DLL should always have explicit init()/cleanup() kind of functions that can be called by the application after loading and before unloading your DLL. Doing anything in DllMain that could cause other DLLs to be loaded/unloaded is risky and not recommended by Microsoft. In NI-VISA's case, the first viOpenDefaultRM in a process loads some of NI-VISA's plugins, and the last viClose() of the RM unloads them, so it is best not to call them from DllMain(). Please refer to this Microsoft document for further details:
http://msdn.microsoft.com/en-us/windows/hardware/gg487379.aspx
Please let us know if you have other questions.
Regards,
Pankaj
05-15-2013 12:39 PM
I understand your use of MSDN to back up your answer. But, we are taking about a change in behaviour that makes C++ objects useless in DLLs, ie in my case a destructor now causes a system deadlock. Don't you think this needs to be addressed with a code change?
04-24-2014 04:58 AM
I have now stumbled over this problem as well. In normal operation I do not rely on cleanup in dllMain and I don't cleanup on process termination in any case, just on FreeLibrary. But in TestStand if somehow the situation arises that an Init call is not paired with a Close call (by using "Abort" for example, or a simple programming error) there is now no way to shutdown TestStand as it tries to FreeLibrary every DLL before quitting. The hang occures in the PXI Device Manager Plugin (NiViPpiD.dll), a component we don't even care about but cannot uninstall because of its ridiculously numerous dependencies.
Again, fortunately we don't rely on the behaviour in normal situations but it's still very annoying that code that has worked fine for over a decade is now broken. On the plus side, people will probably blame TestStand 😉