Page 1 of 1

RCF_AUTO_INIT_DEINIT hang

Posted: Mon Apr 14, 2014 6:10 pm
by miguelluis
This may be related to the post "High CPU load due to RCF AMI thread". That thread referenced a potential fix, but I did not see any code available to try.

I have compiled RCF into a static library that was built with RCF_AUTO_INIT_DEINIT defined.
I then linked this library into a Windows DLL.
When I invoke the Windows LoadLibrary function on this DLL, the process hangs.

Per the following callstack, the hang comes during construction of the AmiThreadPool when the win_iocp_io_service attempts to start a thread and hangs up in the Windows start_thread call.

ntdll.dll!774df8b1()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
ntdll.dll!774df8b1()
KernelBase.dll!75490a91()
> AnyModalCaptureCtrl.dll!asio::detail::win_thread::start_thread(asio::detail::win_thread::func_base * arg=0x05291d18, unsigned int stack_size=65536) Line 97 + 0xe bytes C++
AnyModalCaptureCtrl.dll!asio::detail::win_thread::win_thread<asio::detail::win_iocp_io_service::timer_thread_function>(asio::detail::win_iocp_io_service::timer_thread_function f={...}, unsigned int stack_size=65536) Line 71 C++
AnyModalCaptureCtrl.dll!asio::detail::win_iocp_io_service::do_add_timer_queue(asio::detail::timer_queue_base & queue={...}) Line 464 + 0x31 bytes C++
AnyModalCaptureCtrl.dll!asio::detail::win_iocp_io_service::add_timer_queue<asio::time_traits<boost::posix_time::ptime> >(asio::detail::timer_queue<asio::time_traits<boost::posix_time::ptime> > & queue={...}) Line 64 C++
AnyModalCaptureCtrl.dll!asio::detail::deadline_timer_service<asio::time_traits<boost::posix_time::ptime> >::deadline_timer_service<asio::time_traits<boost::posix_time::ptime> >(asio::io_service & io_service={...}) Line 67 C++
AnyModalCaptureCtrl.dll!asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> >::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> >(asio::io_service & io_service={...}) Line 71 + 0x6d bytes C++
AnyModalCaptureCtrl.dll!asio::detail::service_registry::create<asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >(asio::io_service & owner={...}) Line 62 + 0x2f bytes C++
AnyModalCaptureCtrl.dll!asio::detail::service_registry::do_use_service(const asio::io_service::service::key & key={...}, asio::io_service::service * (asio::io_service &)* factory=0x018330a4) Line 98 + 0xc bytes C++
AnyModalCaptureCtrl.dll!asio::detail::service_registry::use_service<asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >() Line 30 C++
AnyModalCaptureCtrl.dll!asio::use_service<asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >(asio::io_service & ios={...}) Line 32 C++
AnyModalCaptureCtrl.dll!asio::basic_io_object<asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >::basic_io_object<asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >(asio::io_service & io_service={...}) Line 73 + 0x5a bytes C++
AnyModalCaptureCtrl.dll!asio::basic_deadline_timer<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime>,asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >::basic_deadline_timer<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime>,asio::deadline_timer_service<boost::posix_time::ptime,asio::time_traits<boost::posix_time::ptime> > >(asio::io_service & io_service={...}) Line 144 + 0x4e bytes C++
AnyModalCaptureCtrl.dll!RCF::AsioTimer::AsioTimer(asio::io_service & ioService={...}) Line 35 + 0x4e bytes C++
AnyModalCaptureCtrl.dll!RCF::AsioMuxer::AsioMuxer() Line 156 + 0x72 bytes C++
AnyModalCaptureCtrl.dll!RCF::ThreadPool::enableMuxerType(RCF::MuxerType muxerType=Mt_Asio) Line 352 + 0x2b bytes C++
AnyModalCaptureCtrl.dll!RCF::AmiThreadPool::AmiThreadPool() Line 306 C++
AnyModalCaptureCtrl.dll!RCF::init(RCF::RcfConfigurationDetectMismatches<1,0,0,0> * __formal=0x00000000) Line 121 + 0x2b bytes C++
AnyModalCaptureCtrl.dll!RCF::RcfInitDeinit::RcfInitDeinit(RCF::RcfConfigurationDetectMismatches<1,0,0,0> * __formal=0x00000000) Line 185 + 0x7 bytes C++
AnyModalCaptureCtrl.dll!RCF::`dynamic initializer for 'gRcfAutoInit''() Line 199 + 0x2a bytes C++
AnyModalCaptureCtrl.dll!_initterm(void (void)* * pfbegin=0x0335ede8, void (void)* * pfend=0x0335f794) Line 903 C
AnyModalCaptureCtrl.dll!_cinit(int initFloatingPrecision=0) Line 307 + 0xf bytes C
AnyModalCaptureCtrl.dll!_CRT_INIT(void * hDllHandle=0x00ac0000, unsigned long dwReason=1, void * lpreserved=0x00000000) Line 132 + 0x19 bytes C
AnyModalCaptureCtrl.dll!__DllMainCRTStartup(void * hDllHandle=0x00ac0000, unsigned long dwReason=1, void * lpreserved=0x00000000) Line 312 + 0x11 bytes C
AnyModalCaptureCtrl.dll!_DllMainCRTStartup(void * hDllHandle=0x00ac0000, unsigned long dwReason=1, void * lpreserved=0x00000000) Line 281 + 0x11 bytes C
ntdll.dll!774f9950()
ntdll.dll!774fd8c9()
ntdll.dll!774fc4d5()
ntdll.dll!774f7d93()
KernelBase.dll!75492288()
KernelBase.dll!754922e5()
Libtest.exe!main(int argc=1, char * * argv=0x00885808) Line 11 + 0x1b bytes C++
Libtest.exe!__tmainCRTStartup() Line 586 + 0x19 bytes C
Libtest.exe!mainCRTStartup() Line 403 C
kernel32.dll!759f339a()
ntdll.dll!774f9ef2()
ntdll.dll!774f9ec5()

Please let me know if there is a resolution to this issue.

Thanks.

- Mike

Re: RCF_AUTO_INIT_DEINIT hang

Posted: Sun Apr 20, 2014 11:27 am
by jarl
Hi Mike,

The problem is that RCF::init() is being called from DllMain() in your DLL. This happens because when RCF_AUTO_INIT_DEINIT is defined, RCF contains a global static RcfInitDeinit object, which is executed automatically when the module is loaded.

This works fine for executables, but is dangerous for DLL's. As documented in the link below, DllMain() is not a good place to be doing any application specific initialization, due to how Windows implements DLL loading:

http://msdn.microsoft.com/en-us/library ... s.85).aspx

Hence we recommend not defining RCF_AUTO_INIT_DEINIT if you are building RCF into a DLL. A better way to manage initialization is to instantiate RcfInitDeinit objects explictly in your application code, to match the lifetime of the RCF objects you are using. Because RCF initialization is ref counted, you can instantiate many RcfInitDeinit objects , and deinitialization will only take place when the last one is destroyed.