Results 1 to 9 of 9

Thread: Ice 'hangs' in destroy when called through DLL

  1. #1
    DaVinci79 is offline Registered User
    Name: Vincent vanBeveren
    Organization: FOM Rijnhuizen
    Project: Remote access research data Magnum PSI
    Join Date
    Oct 2008
    Posts
    9

    Ice 'hangs' in destroy when called through DLL

    Hi everyone,

    I'm wrapping Ice 3.3.0 into a DLL (VS 2008) However I am not able to get it up and running properly. The problem is that Ice hangs when I try to unload the DLL. Even if I did not do anything but load and unload the DLL. I did not create any proxy instances, and not created any connections.

    I have the following DLL main:

    Code:
    BOOL APIENTRY DllMain( HANDLE hModule, 
                           DWORD  ul_reason_for_call, 
                           LPVOID lpReserved) 
    {
    	if (ul_reason_for_call == DLL_PROCESS_ATTACH) 
    	{
    		try 
    		{
    			// initialize Ice when DLL is loaded.
    			Ice::PropertiesPtr props = Ice::createProperties();
    			props->setProperty("Ice.MessageSizeMax", "10240");
    
    			Ice::InitializationData data;
    			data.properties = props;
    			ic = Ice::initialize(data);
    		} catch (const Ice::Exception& ex) {
    			return FALSE;
    		}
    	} else if (ul_reason_for_call == DLL_PROCESS_DETACH) {
    		// destroy Ice when DLL is unloaded.
    		try {
    			if (ic) {
    				/*ic->shutdown();
    				ic->waitForShutdown();*/
    				ic->destroy();
    			}
    		} catch (const Ice::Exception& ex) {
    			// return true, even though things go wrong.
    			return TRUE;
    		}
    	}
        return TRUE;
    }
    And i wrote the following test application:

    Code:
    int _tmain(int argc, _TCHAR* argv[])
    {
    		/* get handle to dll */
    	HINSTANCE hGetProcIDDLL = LoadLibrary(_T("H:\\vc\\magnumDll\\Debug\\magnum.dll"));
    
       /* Release the Dll */
       FreeLibrary(hGetProcIDDLL);
    
    	return 0;
    }
    When I run this it hangs at ic->destroy().

    Here is the call-stack
    Code:
     	ntdll.dll!7c90e4f4() 	
     	[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]	
     	ntdll.dll!7c90df3c() 	
     	kernel32.dll!7c8025db() 	
     	kernel32.dll!7c802542() 	
    >	iceutil33d.dll!IceUtil::ThreadControl::join()  Line 61 + 0x10 bytes	C++
     	iceutil33d.dll!IceUtil::Timer::destroy()  Line 44	C++
     	ice33d.dll!IceInternal::Instance::destroy()  Line 1246 + 0x18 bytes	C++
     	ice33d.dll!Ice::CommunicatorI::destroy()  Line 74 + 0x12 bytes	C++
     	magnum.dll!DllMain(void * hModule=0x10000000, unsigned long ul_reason_for_call=0, void * lpReserved=0x00000000)  Line 72 + 0x30 bytes	C++
     	magnum.dll!__DllMainCRTStartup(void * hDllHandle=0x10000000, unsigned long dwReason=0, void * lpreserved=0x00000000)  Line 543 + 0x11 bytes	C
     	magnum.dll!_DllMainCRTStartup(void * hDllHandle=0x10000000, unsigned long dwReason=0, void * lpreserved=0x00000000)  Line 507 + 0x11 bytes	C
     	ntdll.dll!7c90118a() 	
     	ntdll.dll!7c91e024() 	
     	kernel32.dll!7c801bea() 	
     	kernel32.dll!7c80ac87() 	
     	callDll.exe!main(int argc=1, char * * argv=0x00330f80)  Line 31 + 0xc bytes	C++
     	callDll.exe!mainCRTStartup()  Line 259 + 0x19 bytes	C
     	kernel32.dll!7c817067() 	
     	ice33d.dll!IceInternal::Instance::Instance(const IceInternal::Handle<Ice::Communicator> & communicator={...}, const Ice::InitializationData & initData={...})  Line 980 + 0x59 bytes	C++
     	c483003e()
    As far as I know it waits for the timer to die, but it never does. From the Autos window I can see that _destroyed has been set to true.

    The _timer instance contains the following values:
    Code:
    -		this	0x00a2bec0 {_monitor={...} _destroyed=true _tokens=[0]() ...}	IceUtil::Timer * const
    +		IceUtil::Shared	{_ref=1 _noDelete=false }	IceUtil::Shared
    -		IceUtil::Thread	{_stateMutex={...} _started=true _running=false ...}	IceUtil::Thread
    +		IceUtil::Shared	{_ref=1 _noDelete=false }	IceUtil::Shared
    +		__vfptr	0x003d890c const IceUtil::Timer::`vftable'{for `IceUtil::Thread'}	*
    +		_stateMutex	{_mutex={...} }	IceUtil::Mutex
    		_started	true	bool
    		_running	false	bool
    		_handle	0x0000009c	void *
    		_id	3300	unsigned long
    -		_monitor	{_cond={...} _mutex={...} _nnotify=0 }	IceUtil::Monitor<IceUtil::Mutex>
    +		_cond	{_internal={...} _gate={...} _queue={...} ...}	IceUtil::Cond
    +		_mutex	{_mutex={...} }	IceUtil::Mutex
    		_nnotify	0	int
    		_destroyed	true	bool
    		_tokens	[0]()	std::set<IceUtil::Timer::Token,std::less<IceUtil::Timer::Token>,std::allocator<IceUtil::Timer::Token> >
    		_tasks	[0]()	std::map<IceUtil::Handle<IceUtil::TimerTask>,IceUtil::Time,IceUtil::Timer::TimerTaskCompare,std::allocator<std::pair<IceUtil::Handle<IceUtil::TimerTask> const ,IceUtil::Time> > >
    +		_wakeUpTime	{_usec=26506316554 }	IceUtil::Time

    I had a similar problem with Ice 3.2.1, at that point the ConnectionMonitor did not die (I didn't create any connections then either, connections set was empty). That is why I upgraded the whole thing to Ice 3.3.0.

    Strangly enough if I do not build a DLL, but instantiate Ice from a Console application it works fine. Is there something I am missing?

    Regards,
    Vincent

  2. #2
    matthew's Avatar
    matthew is offline ZeroC Staff
    Name: Matthew Newhook
    Organization: ZeroC, Inc.
    Project: Internet Communications Engine
    Join Date
    Feb 2003
    Location
    NL, Canada
    Posts
    1,458
    Are you mixing the debug & release runtime DLLs in your application?

  3. #3
    DaVinci79 is offline Registered User
    Name: Vincent vanBeveren
    Organization: FOM Rijnhuizen
    Project: Remote access research data Magnum PSI
    Join Date
    Oct 2008
    Posts
    9
    Hi Metthew,

    No, I created a DLL using /MDd, and linking the iced and iceutild libs.

    This is the commandline for the compiler creating the DLL:
    Code:
    /Od /I "C:\Ice-3.3.0-VC90\include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_USRDLL" /D "MAGNUMDLL_EXPORTS" /D "_WINDLL" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Fo"Debug\\" /Fd"Debug\vc90.pdb" /W3 /nologo /c /ZI /TP /errorReport:prompt
    And this for the linker, linking the DLL:
    Code:
    /OUT:"\\Rijnh\shares\Users\beveren\vc\magnumDll\Debug\magnum.dll" /INCREMENTAL /NOLOGO /LIBPATH:"C:\Ice-3.3.0-VC90\lib" /DLL /MANIFEST /MANIFESTFILE:"Debug\magnum.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"\\rijnh\shares\Users\beveren\vc\magnumDll\Debug\magnum.pdb" /SUBSYSTEM:WINDOWS /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:PROMPT iced.lib iceutild.lib  kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
    Regards,
    Vincent

  4. #4
    DaVinci79 is offline Registered User
    Name: Vincent vanBeveren
    Organization: FOM Rijnhuizen
    Project: Remote access research data Magnum PSI
    Join Date
    Oct 2008
    Posts
    9
    As an addition I noticed it only goes wrong when invoking it from the DllMain function (invoked by the kernel when FreeLibrary is invoked).

    If I would create a DLL function deinit, and invoke ic->destory() there it does go right. However, I wish to perform clean up outside of the control of the people using the library, since it will probably be used by non-programmers in LabView.

  5. #5
    bernard's Avatar
    bernard is offline ZeroC Staff
    Name: Bernard Normier
    Organization: ZeroC, Inc.
    Project: Ice
    Join Date
    Feb 2003
    Location
    Palm Beach Gardens, FL
    Posts
    1,294
    Hi Vincent,

    I think this the problem:
    The Old New Thing : Another reason not to do anything scary in your DllMain: Inadvertent deadlock

    destroy() on the Ice communicator instructs the communicator to destroy its thread pools, and "join" these threads. Join is waiting on the thread's handle (Terminating a Thread (Windows)):

    Code:
        int rc = WaitForSingleObject(_handle, INFINITE);
    I suspect this handle is signaled only after the thread has completed the DLL_THREAD_DETACH, which is blocked on the loader lock. You should be able to confirm this in the debugger.

    Cheers,
    Bernard
    Bernard Normier
    ZeroC, Inc.

  6. #6
    DaVinci79 is offline Registered User
    Name: Vincent vanBeveren
    Organization: FOM Rijnhuizen
    Project: Remote access research data Magnum PSI
    Join Date
    Oct 2008
    Posts
    9
    Hey Bernard,

    Thank you for your reply. Yes, that is exactly where it hangs. From what I gather it is very likely that this is indeed what is going on.

    If I understand correctly there is no solution for it inside the scope of the DllMain.

    I could in theory start another thread to invoke the ic->destroy()... but that would be evil, since it will run partially after the DLL_PROCESS_DETACH has been completed.

    Do you have a suggestion for a solution, (besides moving it outside the loader lock)?

    Regards,
    Vincent

  7. #7
    bernard's Avatar
    bernard is offline ZeroC Staff
    Name: Bernard Normier
    Organization: ZeroC, Inc.
    Project: Ice
    Join Date
    Feb 2003
    Location
    Palm Beach Gardens, FL
    Posts
    1,294
    Hi Vincent,

    The best solution is to destroy your Ice communicator before this DLL unloading. I hope you can find a way to do that in your app.

    Cheers,
    Bernard
    Bernard Normier
    ZeroC, Inc.

  8. #8
    DaVinci79 is offline Registered User
    Name: Vincent vanBeveren
    Organization: FOM Rijnhuizen
    Project: Remote access research data Magnum PSI
    Join Date
    Oct 2008
    Posts
    9
    Yes, I was afraid so... well, we'll just hope that they use the LabView components properly

    Thank you for your quick reply.

    Vincent

  9. #9
    adam3914 is offline Registered User
    Name: Adam Kalb
    Organization: University of Rochester Laser labs
    Project: Remote Image Acquisition
    Join Date
    Oct 2008
    Posts
    6
    I am having the same problem, I am using a c++ dll in matlab. If I unload the dll without destroying the communicator, matlab crashes after a few minutes. What I ended up doing was constantly connecting and disconnecting so that when the dll was unloaded it would already be disconnected. Their didn't appear to be much of a performance loss doing this way.

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Similar Threads

  1. Replies: 7
    Last Post: 11-03-2010, 01:27 PM
  2. Ice.Application run method never called
    By lafayej in forum Help Center
    Replies: 0
    Last Post: 10-25-2010, 08:43 AM
  3. Ice Destroy In Java
    By aswani in forum Help Center
    Replies: 1
    Last Post: 08-11-2008, 12:54 AM
  4. Replies: 2
    Last Post: 07-14-2008, 11:37 AM
  5. Terminate called on Ice::FileException in IcePy
    By joshmoore in forum Bug Reports
    Replies: 4
    Last Post: 08-28-2007, 01:03 PM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •