Discussion:
[omniORB] Crash in VS8 with static runtime
Arne Pajunen
2006-10-27 17:00:52 UTC
Permalink
Hi,

I found that OmniOrb 4.0.7 stable crashes when compiled with Visual
studio 2005 (vs8) static runtime (/MT) under certain circumstances.

The problem manifested for me when resolving NameService (testcase
source code attached) with a crash in release mode that disappears when
compiling for debug, or even with debug information. The problem
occurred when both OmniOrb libraries and the program were compiled with
/MT runtime, and disappeared sporadically.

I've tracked the cause to be the linker option "/OPT:REF" which gets
enabled by default for release builds, and disabled in debug. It enabled
"identical COMDAT folding", which to my understanding removes identical
functions and keeps just one. This causes a crash because it folds some
things it shouldn't, as you can see from the attached verbose linker
output snippet. It replaces the omniIdentity classes (Local,Remote,..)
thisClassCompare with a single copy, and because the classes are
identified by the function pointer (if I understood correctly), all
comparisons become true.

This causes the crash in my scenario in createObjRef (omniInternal.cc),
as you can see from the attached stacktrace (minimal) and program
outputs. It falsely identifies remoteIdentities as local and promptly
crashes.

As a workaround, you can build projects with static runtime that link
OmniOrb libraries with /OPT:NOICF , which disables the duplicate removal
and makes the code work. However, I think it would be beneficial in the
long run to change this code so it compiles correctly with /OPT:ICF
which is a default for new projects in VS2005.

Although I detected this in 4.0.7 and haven't tried newer versions, I
believe omniORB-4.1.0-beta2 to be affected as well because the relevant
sections of code seem similar.

I would be most interested in any thoughts, and ideas for a patch.

Best regards,
--
Arne Pajunen
Software Engineer
OpenTTCN Oy, Test and Test Control Components for Test System Vendors
Web: http://www.openttcn.com

-------------- next part --------------
stack trace of crashing program in release mode with "Program database" debugging,
no edit&continue, optimized, /opt:ref /opt:icf

abababab()
omnitest.exe!omni::createObjRef() + 0x8e bytes C++
omnitest.exe!omniObjRef::_realNarrow() + 0x217 bytes C++
omnitest.exe!CosNaming::NamingContext::_narrow() + 0x1f bytes C++
omnitest.exe!main(int argc=1, char * * argv=0x00573648) Line 104 + 0x6 bytes C++
omnitest.exe!__tmainCRTStartup() Line 318 + 0x12 bytes C
kernel32.dll!7d4e992a()
[Frames below may be incorrect and/or missing, no symbols loaded for kernel32.dll]


-------------- next part --------------
snips from linker output with /opt:ref, /opt:icf, /verbose

2> Discarded "public: void * (__cdecl*__thiscall omniIdentity::classCompare(void))(class omniIdentity *,void *)" (?***@omniIdentity@@***@PAX@ZXZ) from omniORB4.lib(omniInternal.o)
...


2> Selected symbol:
2> "public: static void * __cdecl omniLocalIdentity::thisClassCompare(class omniIdentity *,void *)" (?***@omniLocalIdentity@@SAPAXPAVomniIdentity@@***@Z) from omniORB4.lib(localIdentity.o)
2> Replaced symbol(s):
2> "public: static void * __cdecl omniRemoteIdentity::thisClassCompare(class omniIdentity *,void *)" (?***@omniRemoteIdentity@@SAPAXPAVomniIdentity@@***@Z) from omniORB4.lib(remoteIdentity.o)
2> "public: static void * __cdecl omniInProcessIdentity::thisClassCompare(class omniIdentity *,void *)" (?***@omniInProcessIdentity@@SAPAXPAVomniIdentity@@***@Z) from omniORB4.lib(inProcessIdentity.o)
2> "public: static void * __cdecl omniShutdownIdentity::thisClassCompare(class omniIdentity *,void *)" (?***@omniShutdownIdentity@@SAPAXPAVomniIdentity@@***@Z) from omniORB4.lib(shutdownIdentity.o)


-------------- next part --------------
omniORB: (0) Distribution date: Fri Jan 13 13:47:35 GMT 2006 dgrisby
omniORB: (0) My addresses are:
omniORB: 192.168.11.11
omniORB: 192.168.147.1
omniORB: 192.168.242.1
omniORB: 127.0.0.1
omniORB: (0) Maximum supported GIOP version is 1.2
omniORB: (0) Native char code sets: ISO-8859-1 UTF-8.
omniORB: (0) Transmission char code sets: ISO-8859-1(1.2) ISO-8859-1(1.1) ISO-8859-1(1.0) UTF-8(1.2) UTF-8(1.1).
omniORB: (0) Native wide char code sets: UTF-16.
omniORB: (0) Transmission wide char code sets: UTF-16(1.2).
omniORB: (0) Initialising omniDynamic library.
omniORB: (0) Current configuration is as follows:
omniORB: DefaultInitRef (file) =
omniORB: DefaultInitRef (args) =
omniORB: InitRef = NameService=corbaname::localhost
omniORB: abortOnInternalError = 0
omniORB: abortOnNativeException = 0
omniORB: acceptBiDirectionalGIOP = 0
omniORB: acceptMisalignedTcIndirections = 0
omniORB: bootstrapAgentHostname =
omniORB: bootstrapAgentPort = 900
omniORB: clientCallTimeOutPeriod = 0
omniORB: clientTransportRule = * unix,ssl,tcp
omniORB: configFile = [none]
omniORB: connectionWatchImmediate = 0
omniORB: connectionWatchPeriod = 50000
omniORB: diiThrowsSysExceptions = 0
omniORB: dumpConfiguration = 0
omniORB: endPoint = giop:tcp::
omniORB: endPointPublishAllIFs = 0
omniORB: giopMaxMsgSize = 2097152
omniORB: giopTargetAddressMode = KeyAddr
omniORB: id = omniORB4
omniORB: inConScanPeriod = 180
omniORB: lcdMode = 0
omniORB: maxGIOPConnectionPerServer = 5
omniORB: maxGIOPVersion = 1.2
omniORB: maxInterleavedCallsPerConnection = 5
omniORB: maxServerThreadPerConnection = 100
omniORB: maxServerThreadPoolSize = 100
omniORB: maxSocketRecv = 131072
omniORB: maxSocketSend = 131072
omniORB: nativeCharCodeSet = ISO-8859-1
omniORB: nativeWCharCodeSet = UTF-16
omniORB: objectTableSize = 0
omniORB: offerBiDirectionalGIOP = 0
omniORB: omniORB_27_CompatibleAnyExtraction = 0
omniORB: oneCallPerConnection = 1
omniORB: outConScanPeriod = 120
omniORB: poaHoldRequestTimeout = 0
omniORB: poaUniquePersistentSystemIds = 1
omniORB: principal = [Null]
omniORB: scanGranularity = 5
omniORB: serverCallTimeOutPeriod = 0
omniORB: serverTransportRule = * unix,ssl,tcp
omniORB: strictIIOP = 1
omniORB: supportBootstrapAgent = 0
omniORB: supportCurrent = 1
omniORB: supportPerThreadTimeOut = 0
omniORB: tcAliasExpand = 0
omniORB: threadPerConnectionLowerLimit = 9000
omniORB: threadPerConnectionPolicy = 1
omniORB: threadPerConnectionUpperLimit = 10000
omniORB: threadPoolWatchConnection = 1
omniORB: traceExceptions = 1
omniORB: traceFile = omnilog.txt
omniORB: traceInvocations = 1
omniORB: traceLevel = 99
omniORB: traceThreadId = 1
omniORB: unixTransportDirectory = /tmp/omni-%u
omniORB: unixTransportPermission = 777
omniORB: useTypeCodeIndirections = 1
omniORB: verifyObjectExistsAndType = 1
omniORB: (0) Initialising incoming endpoints.
omniORB: (0) Bind to address 0.0.0.0.
omniORB: (0) Starting serving incoming endpoints.
omniORB: (1) AsyncInvoker: thread id = 1 has started. Total threads = 1
omniORB: (1) giopRendezvouser task execute for giop:tcp:192.168.11.11:1275
omniORB: (0) Creating ref to remote: key<NameService>
target id : IDL:omg.org/CORBA/Object:1.0
most derived id:
omniORB: (0) Initial reference `NameService' resolved from configuration file.
omniORB: (0) Invoke '_non_existent' on remote: key<NameService>
omniORB: (0) Client attempt to connect to giop:tcp:localhost:2809
omniORB: (2) AsyncInvoker: thread id = 2 has started. Total threads = 2
omniORB: (2) Scavenger task execute.
omniORB: (0) Client opened connection to giop:tcp:127.0.0.1:2809
omniORB: (0) sendChunk: to giop:tcp:127.0.0.1:2809 64 bytes
omniORB: (0)
4749 4f50 0100 0100 3400 0000 0000 0000 GIOP....4.......
0200 0000 01cd cdcd 0b00 0000 4e61 6d65 ............Name
5365 7276 6963 65cd 0e00 0000 5f6e 6f6e Service....._non
5f65 7869 7374 656e 7400 cdcd 0000 0000 _existent.......
omniORB: (0) inputMessage: from giop:tcp:127.0.0.1:2809 25 bytes
omniORB: (0)
4749 4f50 0100 0101 0d00 0000 0000 0000 GIOP............
0200 0000 0000 0000 00 .........
omniORB: (0) Invoke '_is_a' on remote: key<NameService>
omniORB: (0) sendChunk: to giop:tcp:127.0.0.1:2809 100 bytes
omniORB: (0)
4749 4f50 0100 0100 5800 0000 0000 0000 GIOP....X.......
0400 0000 01cd cdcd 0b00 0000 4e61 6d65 ............Name
5365 7276 6963 65cd 0600 0000 5f69 735f Service....._is_
6100 7869 0000 0000 2800 0000 4944 4c3a a.xi....(...IDL:
6f6d 672e 6f72 672f 436f 734e 616d 696e omg.org/CosNamin
672f 4e61 6d69 6e67 436f 6e74 6578 743a g/NamingContext:
312e 3000 1.0.
omniORB: (0) inputMessage: from giop:tcp:127.0.0.1:2809 25 bytes
omniORB: (0)
4749 4f50 0100 0101 0d00 0000 0000 0000 GIOP............
0400 0000 0000 0000 01 .........
omniORB: (0) Creating ref to remote: key<NameService>
target id : IDL:omg.org/CosNaming/NamingContext:1.0
most derived id:
omniORB: (0) ObjRef() -- deleted.
omniORB: (0) omniRemoteIdentity deleted.
omniORB: (0) ObjRef() -- deleted.
omniORB: (0) ORB not destroyed; no final clean-up.

-------------- next part --------------
main(): starting.
main():call Initializer::init()
omniORB: (0) Distribution date: Fri Jan 13 13:47:35 GMT 2006 dgrisby
omniORB: (0) My addresses are:
omniORB: 192.168.11.11
omniORB: 192.168.147.1
omniORB: 192.168.242.1
omniORB: 127.0.0.1
omniORB: (0) Maximum supported GIOP version is 1.2
omniORB: (0) Native char code sets: ISO-8859-1 UTF-8.
omniORB: (0) Transmission char code sets: ISO-8859-1(1.2) ISO-8859-1(1.1) ISO-88
59-1(1.0) UTF-8(1.2) UTF-8(1.1).
omniORB: (0) Native wide char code sets: UTF-16.
omniORB: (0) Transmission wide char code sets: UTF-16(1.2).
omniORB: (0) Initialising omniDynamic library.
omniORB: (0) Current configuration is as follows:
omniORB: DefaultInitRef (file) =
omniORB: DefaultInitRef (args) =
omniORB: InitRef = NameService=corbaname::localhost
omniORB: abortOnInternalError = 0
omniORB: abortOnNativeException = 0
omniORB: acceptBiDirectionalGIOP = 0
omniORB: acceptMisalignedTcIndirections = 0
omniORB: bootstrapAgentHostname =
omniORB: bootstrapAgentPort = 900
omniORB: clientCallTimeOutPeriod = 0
omniORB: clientTransportRule = * unix,ssl,tcp
omniORB: configFile = [none]
omniORB: connectionWatchImmediate = 0
omniORB: connectionWatchPeriod = 50000
omniORB: diiThrowsSysExceptions = 0
omniORB: dumpConfiguration = 0
omniORB: endPoint = giop:tcp::
omniORB: endPointPublishAllIFs = 0
omniORB: giopMaxMsgSize = 2097152
omniORB: giopTargetAddressMode = KeyAddr
omniORB: id = omniORB4
omniORB: inConScanPeriod = 180
omniORB: lcdMode = 0
omniORB: maxGIOPConnectionPerServer = 5
omniORB: maxGIOPVersion = 1.2
omniORB: maxInterleavedCallsPerConnection = 5
omniORB: maxServerThreadPerConnection = 100
omniORB: maxServerThreadPoolSize = 100
omniORB: maxSocketRecv = 131072
omniORB: maxSocketSend = 131072
omniORB: nativeCharCodeSet = ISO-8859-1
omniORB: nativeWCharCodeSet = UTF-16
omniORB: objectTableSize = 0
omniORB: offerBiDirectionalGIOP = 0
omniORB: omniORB_27_CompatibleAnyExtraction = 0
omniORB: oneCallPerConnection = 1
omniORB: outConScanPeriod = 120
omniORB: poaHoldRequestTimeout = 0
omniORB: poaUniquePersistentSystemIds = 1
omniORB: principal = [Null]
omniORB: scanGranularity = 5
omniORB: serverCallTimeOutPeriod = 0
omniORB: serverTransportRule = * unix,ssl,tcp
omniORB: strictIIOP = 1
omniORB: supportBootstrapAgent = 0
omniORB: supportCurrent = 1
omniORB: supportPerThreadTimeOut = 0
omniORB: tcAliasExpand = 0
omniORB: threadPerConnectionLowerLimit = 9000
omniORB: threadPerConnectionPolicy = 1
omniORB: threadPerConnectionUpperLimit = 10000
omniORB: threadPoolWatchConnection = 1
omniORB: traceExceptions = 1
omniORB: traceFile = [stderr]
omniORB: traceInvocations = 1
omniORB: traceLevel = 99
omniORB: traceThreadId = 1
omniORB: unixTransportDirectory = /tmp/omni-%u
omniORB: unixTransportPermission = 777
omniORB: useTypeCodeIndirections = 1
omniORB: verifyObjectExistsAndType = 1
omniORB: (0) Initialising incoming endpoints.
omniORB: (0) Bind to address 0.0.0.0.
omniORB: (0) Starting serving incoming endpoints.
main(omniORB: (1) AsyncInvoker: thread id = 1 has started. Total threads = 1
)omniORB: (1) giopRendezvouser task execute for giop:tcp:192.168.11.11:1283
: done.main(): ORB running.
main(): get NameService object.
omniORB: (0) Creating ref to local: key<NameService>
target id : IDL:omg.org/CORBA/Object:1.0
most derived id:
omniORB: (0) Initial reference `NameService' resolved from configuration file.
main(): check its not nil.
omniORB: (0) Invoke '_non_existent' on remote: key<NameService>
omniORB: (0) Client attempt to connect to giop:tcp:localhost:2809
omniORB: (2) AsyncInvoker: thread id = 2 has started. Total threads = 2
omniORB: (2) Scavenger task execute.
omniORB: (0) Client opened connection to giop:tcp:127.0.0.1:2809
omniORB: (0) sendChunk: to giop:tcp:127.0.0.1:2809 64 bytes
omniORB: (0)
4749 4f50 0100 0100 3400 0000 0000 0000 GIOP....4.......
0200 0000 0100 0000 0b00 0000 4e61 6d65 ............Name
5365 7276 6963 6500 0e00 0000 5f6e 6f6e Service....._non
5f65 7869 7374 656e 7400 0000 0000 0000 _existent.......
omniORB: (0) inputMessage: from giop:tcp:127.0.0.1:2809 25 bytes
omniORB: (0)
4749 4f50 0100 0101 0d00 0000 0000 0000 GIOP............
0200 0000 0000 0000 00 .........
main(): narrowing NamingContext, 0064BC18 (exists)

omniORB: (0) Invoke '_is_a' on remote: key<NameService>
omniORB: (0) sendChunk: to giop:tcp:127.0.0.1:2809 100 bytes
omniORB: (0)
4749 4f50 0100 0100 5800 0000 0000 0000 GIOP....X.......
0400 0000 0100 0000 0b00 0000 4e61 6d65 ............Name
5365 7276 6963 6500 0600 0000 5f69 735f Service....._is_
6100 7869 0000 0000 2800 0000 4944 4c3a a.xi....(...IDL:
6f6d 672e 6f72 672f 436f 734e 616d 696e omg.org/CosNamin
672f 4e61 6d69 6e67 436f 6e74 6578 743a g/NamingContext:
312e 3000 1.0.
omniORB: (0) inputMessage: from giop:tcp:127.0.0.1:2809 25 bytes
omniORB: (0)
4749 4f50 0100 0101 0d00 0000 0000 0000 GIOP............
0400 0000 0000 0000 01 .........


-------------- next part --------------
main(): starting.
main():call Initializer::init()
main(): done.main(): ORB running.
main(): get NameService object.
main(): check its not nil.
main(): narrowing NamingContext, 0098A1B8 (exists)

main(): naming context narrowed ok.
main(): NamingService done.

-------------- next part --------------

#include <string>
#include <iostream>
#include <vector>

using namespace std;

#include <CORBA.h>
#include <Naming.hh>

static CORBA::ORB_var _orb;
static PortableServer::POA_var _rootPOA;
static PortableServer::POAManager_var _manager;

static CosNaming::NamingContext_var _ns_ctx;
//static CosNaming::NamingContext_var _root;

int main (int argc, char** argv)
{
int i;
string opName ("main()");

cout << opName << ": starting.\n";

int total_arg_count = 2;

const char** corba_args =
(const char **) malloc((total_arg_count + 1) * sizeof(char *));

corba_args[0] = "-ORBverifyObjectExistsAndType";
corba_args[1] = "1";
/*corba_args[2] = "-ORBtraceExceptions";
corba_args[3] = "1";
corba_args[4] = "-ORBtraceInvocations";
corba_args[5] = "1";
corba_args[6] = "-ORBtraceThreadId";
corba_args[7] = "1";
corba_args[8] = "-ORBtraceLevel";
corba_args[9] = "99";*/
corba_args[total_arg_count] = 0;

bool succeeded = true;

cout << opName << ":call Initializer::init()\n";

try {
// Initialise the ORB.
_orb = CORBA::ORB_init(total_arg_count, (char**)corba_args);

// Obtain a reference to the root POA.
CORBA::Object_var poaObject(
_orb->resolve_initial_references("RootPOA"));

_rootPOA = PortableServer::POA::_narrow(poaObject);

// Obtain a POAManager
_manager = _rootPOA->the_POAManager();

} catch (...) {
succeeded = false;
}

cout << opName << ": done.";

free(corba_args);

if (!succeeded) {
return 1;
}

_manager->activate();

cout << opName << ": ORB running.\n";

int status;

// Resolve CORBA Naming Service initial reference:
// Example of corbaloc: "corbaloc::127.0.0.1:5500/NameService"
string corbaloc_prefix = string() +
"corbaloc::127.0.0.1:2809/";
string ns_corbaloc = corbaloc_prefix + "NameService";

CORBA::Object_var obj;

try
{
cout << opName << ": get NameService object.\n";

//obj = orb->string_to_object(ns_corbaloc.c_str());
obj = _orb->resolve_initial_references("NameService");

cout << opName << ": check its not nil.\n";

if (CORBA::is_nil(obj))
{
cout << opName << ": NameService object nil, exiting\n";
return 4;
}

cout << opName << ": narrowing NamingContext, " << obj << " ("
<< ((obj->_non_existent())?"nonexistent":"exists") << ")\n";
cout << endl << std::flush;

_ns_ctx = CosNaming::NamingContext::_narrow(obj); // This crashes.

cout << opName << ": naming context narrowed ok." << endl << flush;

if (CORBA::is_nil(_ns_ctx))
{
cout << opName << ": Error: Cannot narrow "
"Naming Service initial reference." << endl;
return 5;
}
}
catch (...)
{
succeeded = false;
}

cout << opName << ": NamingService done.\n";

if (!succeeded)
{

cout << opName << ": Error: "
"Cannot locate NameService." << endl;


return 2;
}
}
Arne Pajunen
2006-10-27 20:10:51 UTC
Permalink
Hi,

I just thought I'd mention that it seems to be very easy to work around
this issue. The affected pieces are just a homemade dynamic_cast, so if
you have RTTI support (like vs2005), you can just implement the downcast
operations with dynamic_cast. The pieces to modify are the downcast
member in omniIdentity, omniLocalIdentity, omniShutdownIdentity,
omniInProcessIdentity, omniRemoteIdentity and omniObjTableEntry. I also
changed the thisClassCompares to use dynamic_cast for good measure,
although this doesn't seem necessary. To keep the fallback
functionality, just put the dynamic_cast implementation in #ifdef
_CPPRTTI blocks (maybe && _MSC_VER >= 1400) and it will fallback to old
behavior with no RTTI.

Any thoughts on this ? I'm currently testing this and it seems to work
without problems, if anyone needs it I can put these (minor) changes in
a diff and post here next week.

ps. There was also some fishy looking code in omniObjTableEntry's
thisClassCompare (omniInternal.cc), it cast it to either
omniObjTableEntry, or fallback to omniLocalIdentity and the cast that to
omniObjTableEntry with c-style cast. I don't know what the intended
behavior of that is so I just duplicated the effect with
dynamic_casting, maybe someone else knows what the part is supposed to do?

Best Regards,
Arne Pajunen
Post by Arne Pajunen
Hi,
I found that OmniOrb 4.0.7 stable crashes when compiled with Visual
studio 2005 (vs8) static runtime (/MT) under certain circumstances.
The problem manifested for me when resolving NameService (testcase
source code attached) with a crash in release mode that disappears when
compiling for debug, or even with debug information. The problem
occurred when both OmniOrb libraries and the program were compiled with
/MT runtime, and disappeared sporadically.
I've tracked the cause to be the linker option "/OPT:REF" which gets
enabled by default for release builds, and disabled in debug. It enabled
"identical COMDAT folding", which to my understanding removes identical
functions and keeps just one. This causes a crash because it folds some
things it shouldn't, as you can see from the attached verbose linker
output snippet. It replaces the omniIdentity classes (Local,Remote,..)
thisClassCompare with a single copy, and because the classes are
identified by the function pointer (if I understood correctly), all
comparisons become true.
This causes the crash in my scenario in createObjRef (omniInternal.cc),
as you can see from the attached stacktrace (minimal) and program
outputs. It falsely identifies remoteIdentities as local and promptly
crashes.
As a workaround, you can build projects with static runtime that link
OmniOrb libraries with /OPT:NOICF , which disables the duplicate removal
and makes the code work. However, I think it would be beneficial in the
long run to change this code so it compiles correctly with /OPT:ICF
which is a default for new projects in VS2005.
Although I detected this in 4.0.7 and haven't tried newer versions, I
believe omniORB-4.1.0-beta2 to be affected as well because the relevant
sections of code seem similar.
I would be most interested in any thoughts, and ideas for a patch.
Best regards,
--
Arne Pajunen
Software Engineer
OpenTTCN Oy, Test and Test Control Components for Test System Vendors
Web: http://www.openttcn.com
Email: ***@openttcn.fi
Continue reading on narkive:
Loading...