Instrument Control (GPIB, Serial, VISA, IVI)

cancel
Showing results for 
Search instead for 
Did you mean: 

viClose deadlocking in the DllMain function of a DLL

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?

0 Kudos
Message 1 of 10
(4,825 Views)

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.

 

0 Kudos
Message 2 of 10
(4,812 Views)

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

0 Kudos
Message 3 of 10
(4,771 Views)

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

0 Kudos
Message 4 of 10
(4,765 Views)

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.

0 Kudos
Message 5 of 10
(4,736 Views)

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.

0 Kudos
Message 6 of 10
(4,734 Views)

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.

0 Kudos
Message 7 of 10
(4,729 Views)

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

0 Kudos
Message 8 of 10
(4,715 Views)

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?

0 Kudos
Message 9 of 10
(4,707 Views)

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 😉

0 Kudos
Message 10 of 10
(4,454 Views)