edisona / rcf-cpp

Automatically exported from code.google.com/p/rcf-cpp
1 stars 0 forks source link

Assert on RCF global initialization #33

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Hello,

Is it possible to instantiate init class RCF::RcfInitDeinit globally?
When I try doing so I get an assert in boost library.

All I want is to create RcfClient instance at the application's earliest 
execution time, even before main() function is called.

Thanks.

Original issue reported on code.google.com by zoltan.b...@gmail.com on 23 Dec 2010 at 5:58

GoogleCodeExporter commented 9 years ago

It is possible to have a global static RcfInitDeinit instance (that's what RCF 
does by default).

You can write code like this:

// Global variable.
RCF::RcfInitDeinit * gpRcfInit;

// This may get called before main().
void somefunc()
{
    if (!gpRcfInit)
    {
        gpRcfInit = new RCF::RcfInitDeinit();
    }

    // Create a RcfClient instance.
    // ...
}

, and then when you shutdown,

delete gpRcfInit;

That way you still have some control over when the initialization and 
deinitialization takes place. If you use a global static RcfInitDeinit 
variable, you can run into problems with order of init/deinit, especially if 
you have other application code running before or after main().

I'd be interested in seeing a stack trace of the assert in boost...

Original comment by jarl.lin...@gmail.com on 31 Dec 2010 at 2:22

GoogleCodeExporter commented 9 years ago
Here is my RCF_SERVER class, which is inherited from RCF::RcfServer
RCF_SERVER::RCF_SERVER(const std::string &pipeName, 
                       const std::string &serverCert /* = "" */, 
                       const std::string &serverCertPass /* = "" */, 
                       const std::string &caCert /* = "" */ )
                       : RCF::RcfServer(RCF::Win32NamedPipeEndpoint(util::toTstring(pipeName)))
{
}

When I try to declare instance of RCF_SERVER globally I get the assert 
mentioned above. When I create RCF_SERVER within main() function I don't get 
the assert.
Here is the stack trace of the assert:
//////////////////////////////////////////////////////////////////////////////
Exception:
    Unhandled exception at 0x008282c6 in RCF_SERVER.exe: 0xC0000005: Access violation reading location 0x00000004.

Call Stack:
    RCF_SERVER.exe!RCF::RcfBoostThreads::boost::mutex::do_lock()  Line 52 + 0x3 bytes   C++
    RCF_SERVER.exe!RCF::RcfBoostThreads::boost::detail::thread::lock_ops<RCF::RcfBoostThreads::boost::mutex>::lock(RCF::RcfBoostThreads::boost::mutex & m={...})  Line 51   C++
    RCF_SERVER.exe!RCF::RcfBoostThreads::boost::detail::thread::scoped_lock<RCF::RcfBoostThreads::boost::mutex>::lock()  Line 93 + 0xb bytes    C++
    RCF_SERVER.exe!RCF::RcfBoostThreads::boost::detail::thread::scoped_lock<RCF::RcfBoostThreads::boost::mutex>::scoped_lock<RCF::RcfBoostThreads::boost::mutex>(RCF::RcfBoostThreads::boost::mutex & mx={...}, bool initially_locked=true)  Line 84    C++
    RCF_SERVER.exe!Platform::Threads::detail::scoped_read_lock::lock()  Line 174    C++
    RCF_SERVER.exe!Platform::Threads::detail::scoped_read_lock::scoped_read_lock(Platform::Threads::read_write_mutex & rwm={...})  Line 161 C++
    RCF_SERVER.exe!util::LogManager::isEnabled(int name=1, int level=2)  Line 139 + 0xc bytes   C++
    RCF_SERVER.exe!RCF::RcfServer::addService(boost::shared_ptr<RCF::I_Service> servicePtr={...})  Line 121 + 0x10 bytes    C++
    RCF_SERVER.exe!RCF::RcfServer::addServerTransport(boost::shared_ptr<RCF::I_ServerTransport> serverTransportPtr={...})  Line 269 + 0x26 bytes    C++
    RCF_SERVER.exe!RCF::RcfServer::addEndpoint(const RCF::I_Endpoint & endpoint={...})  Line 1234   C++
    RCF_SERVER.exe!RCF::RcfServer::RcfServer(const RCF::I_Endpoint & endpoint={...})  Line 86   C++
    RCF_SERVER.exe!RCF_SERVER::RCF_SERVER(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & pipeName="TestPipe", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & serverCert="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & serverCertPass="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & caCert="")  Line 467 + 0xbe bytes  C++
    RCF_SERVER.exe!`dynamic initializer for 'server''()  Line 525 + 0xec bytes  C++
    RCF_SERVER.exe!_initterm(void (void)* * pfbegin=0x00c5e260, void (void)* * pfend=0x00c5ee50)  Line 903  C
    RCF_SERVER.exe!_cinit(int initFloatingPrecision=1)  Line 307 + 0xf bytes    C
    RCF_SERVER.exe!__tmainCRTStartup()  Line 249 + 0x7 bytes    C
    RCF_SERVER.exe!wmainCRTStartup()  Line 182  C
    kernel32.dll!RegisterWaitForInputIdle()  + 0x49 bytes   
///////////////////////////////////////////////////////////////////////////////

And the same way I create RCF_CLIENT, which is inherited from my RcfClient.
Same behavior, creating globally gives the boost assert, and no assert if I 
create within main().
Trace for client:
//////////////////////////////////////////////////////////////////////////
Exception:
    Unhandled exception at 0x007d759b in RCF_CLIENT.exe: 0xC0000005: Access violation reading location 0x0000001c.

Call Stack:
    RCF_CLIENT.exe!RCF::RcfBoostThreads::boost::get_slots(bool alloc=false)  Line 107 + 0x7 bytes   C++
    RCF_CLIENT.exe!RCF::RcfBoostThreads::boost::detail::tss::get()  Line 163 + 0x7 bytes    C++
    RCF_CLIENT.exe!RCF::RcfBoostThreads::boost::thread_specific_ptr<RCF::ThreadLocalData>::get()  Line 94 + 0x2b bytes  C++
    RCF_CLIENT.exe!RCF::getThreadLocalData()  Line 59 + 0xb bytes   C++
    RCF_CLIENT.exe!RCF::pushCurrentClientStub(RCF::ClientStub * pClientStub=0x003c37c8)  Line 99 + 0x5 bytes    C++
    RCF_CLIENT.exe!RCF::CurrentClientStubSentry::CurrentClientStubSentry(RCF::ClientStub & clientStub={...})  Line 567 + 0x9 bytes  C++
    RCF_CLIENT.exe!RCF::AllocateClientParameters<unsigned long,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void,RCF::Void>::operator()(RCF::ClientStub & clientStub={...}, const RCF::Void & a1={...}, const RCF::Void & a2={...}, const RCF::Void & a3={...}, const RCF::Void & a4={...}, const RCF::Void & a5={...}, const RCF::Void & a6={...}, const RCF::Void & a7={...}, const RCF::Void & a8={...}, const RCF::Void & a9={...}, const RCF::Void & a10={...}, const RCF::Void & a11={...}, const RCF::Void & a12={...}, const RCF::Void & a13={...}, const RCF::Void & a14={...}, const RCF::Void & a15={...})  Line 1517 + 0xc bytes  C++
    RCF_CLIENT.exe!RcfClient<I_hCmd>::connect(const RCF::CallOptions & callOptions={...})  Line 143 + 0x228 bytes   C++
    RCF_CLIENT.exe!RcfClient<I_hCmd>::connect()  Line 143 + 0x83 bytes  C++
    RCF_CLIENT.exe!RCF_CLIENT::RCF_CLIENT(const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & connectString="TestPipe", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & clientCert="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & clientCertPass="", const std::basic_string<char,std::char_traits<char>,std::allocator<char> > & caCert="")  Line 246 + 0xf bytes  C++
    RCF_CLIENT.exe!`dynamic initializer for 'client''()  Line 264 + 0xee bytes  C++
    RCF_CLIENT.exe!_initterm(void (void)* * pfbegin=0x00c11260, void (void)* * pfend=0x00c11e50)  Line 903  C
    RCF_CLIENT.exe!_cinit(int initFloatingPrecision=1)  Line 307 + 0xf bytes    C
    RCF_CLIENT.exe!__tmainCRTStartup()  Line 249 + 0x7 bytes    C
    RCF_CLIENT.exe!wmainCRTStartup()  Line 182  C
    kernel32.dll!RegisterWaitForInputIdle()  + 0x49 bytes
///////////////////////////////////////////////////////////////////////

You may try declaring RCF::RcfInitDeinit() globally to get the boost assert.

Thanks.

Original comment by zoltan.b...@gmail.com on 7 Jan 2011 at 6:00

GoogleCodeExporter commented 9 years ago

The problem with global static objects is that there is no guarantee in which 
order they will be contstructed. If you have 2 source files, A.cpp and B.cpp in 
your application, and each defines a global static object, then you can't know 
which object will be created first.

If you are using RCF in code that is executed before or after main(), you need 
to explicitly initialize and deinitialize RCF yourself, by calling RCF::init() 
and RCF::deinit().

You can call RCF::init() multiple times, and only the first call will have an 
effect. However, you need to call RCF::deinit() as many times as you have 
called RCF::init().

Typcially you would call RCF::init() and RCF::deinit() in the ctor and dtor of 
the objects that are created before main() is executed.

If you want to determine at which point RCF is being initialized, you can put a 
breakpoint in RCF::init() (InitDeinit.cpp).

Original comment by jarl.lin...@gmail.com on 8 Jan 2011 at 11:35