Discussion:
[omniORB] ORB initialization with endpoint leaks memory if initialization fails
Göttlicher, Dr.-Ing Martin
2009-09-02 19:50:10 UTC
Permalink
Hello,

in a project I have to use an endpoint to initialize the ORB. If the
initialization is successful everything is fine. If the initialization fails
(because the port is already occupied) memory is leaked as shown by the
following run with valgrind:

==19179== Memcheck, a memory error detector.
==19179== Copyright (C) 2002-2008, and GNU GPL'd, by Julian Seward et al.
==19179== Using LibVEX rev 1884, a library for dynamic binary translation.
==19179== Copyright (C) 2004-2008, and GNU GPL'd, by OpenWorks LLP.
==19179== Using valgrind-3.4.1, a dynamic binary instrumentation framework.
==19179== Copyright (C) 2000-2008, and GNU GPL'd, by Julian Seward et al.
==19179== For more details, rerun with: -v
==19179==
OrbWrapper::createInstance(nameserver=corbaloc:iiop:***@localhost:12345/TNameService,
endpoint=giop:tcp:xxx.xxx.xxx.xxx:50000, outConScanPeriod=0,
inConScanPeriod=0, scanGranularity=0, clientCallTimeOutPeriod=0,
clientConnectTimeOutPeriod=0) ...
omniORB: Configuration file "/etc/omniORB.cfg" either does not exist or is not
a file. No settings read.
omniORB: (0) Version: 4.1.4
omniORB: (0) Distribution date: Sun Jul 19 18:35:23 BST 2009 dgrisby
omniORB: (0) My addresses are:
omniORB: 127.0.0.1
omniORB: 127.0.0.2
omniORB: xxx.xxx.xxx.xxx
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) Information: the omniDynamic library is not linked.
omniORB: (0) Current configuration is as follows:
omniORB: DefaultInitRef (file) =
omniORB: DefaultInitRef (args) =
omniORB: InitRef =
NameService=corbaloc:iiop:***@localhost:12345/TNameService
omniORB: abortOnInternalError = 0
omniORB: abortOnNativeException = 0
omniORB: acceptBiDirectionalGIOP = 0
omniORB: accept = 0
omniORB: bootstrapAgentHostname =
omniORB: bootstrapAgentPort = 900
omniORB: clientCallTimeOutPeriod = 0
omniORB: clientConnectTimeOutPeriod = 0
omniORB: clientTransportRule = * unix,ssl,tcp
omniORB: configFile = /etc/omniORB.cfg
omniORB: connectionWatchImmediate = 0
omniORB: connectionWatchPeriod = 50000
omniORB: copyValuesInLocalCalls = 1
omniORB: diiThrowsSysExceptions = 0
omniORB: dumpConfiguration = 0
omniORB: endPoint = giop:tcp:xxx.xxx.xxx.xxx:50000
omniORB: endPointPublish = addr
omniORB: giopMaxMsgSize = 16777216
omniORB: giopTargetAddressMode = KeyAddr
omniORB: id = omniORB4
omniORB: idleThreadTimeout = 10
omniORB: immediateAddressSwitch = 0
omniORB: inConScanPeriod = 0
omniORB: lcdMode = 0
omniORB: max = 5
omniORB: maxGIOPVersion = 1.2
omniORB: max = 5
omniORB: max = 100
omniORB: maxServerThreadPoolSize = 100
omniORB: maxSocketRecv = 2147483647
omniORB: maxSocketSend = 2147483647
omniORB: nativeCharCodeSet = ISO-8859-1
omniORB: nativeWCharCodeSet = UTF-16
omniORB: objectTableSize = 0
omniORB: offerBiDirectionalGIOP = 0
omniORB: oneCallPerConnection = 1
omniORB: outConScanPeriod = 0
omniORB: poaHoldRequestTimeout = 0
omniORB: poaUniquePersistentSystemIds = 1
omniORB: principal = [Null]
omniORB: resetTimeOutOnRetries = 0
omniORB: scanGranularity = 0
omniORB: serverCallTimeOutPeriod = 0
omniORB: serverTransportRule = * unix,ssl,tcp
omniORB: socketSendBuffer = -1
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: traceInvocationReturns = 0
omniORB: traceInvocations = 0
omniORB: traceLevel = 40
omniORB: traceThreadId = 1
omniORB: traceTime = 0
omniORB: unixTransportDirectory = /tmp/omni-%u
omniORB: unixTransportPermission = 777
omniORB: useTypeCodeIndirections = 1
omniORB: validateUTF8 = 0
omniORB: verifyObjectExistsAndType = 1
omniORB: (0) Initialising incoming endpoints.
omniORB: (0) Instantiate endpoint 'giop:tcp:xxx.xxx.xxx.xxx:50000'
omniORB: (0) Explicit bind to host xxx.xxx.xxx.xxx.
omniORB: (0) Bind to address xxx.xxx.xxx.xxx port 50000.
omniORB: (0) Failed to bind to address xxx.xxx.xxx.xxx port 50000. Address in
use?
omniORB: (0) Error: Unable to create an endpoint of this description:
giop:tcp:xxx.xxx.xxx.xxx:50000
omniORB: (0) throw INITIALIZE from objectAdapter.cc:415
(NO,INITIALIZE_TransportError)
CORBA::Exception caught while calling orb->resolve_initial_references()
OrbWrapper::cleanup(orb=0x4464ff8, poa=nil) ...
omniORB: (0) Preparing to shutdown ORB.
omniORB: (0) 0 object references present at ORB shutdown.
omniORB: (0) ORB shutdown is complete.
omniORB: (0) Terminate strand scavenger.
omniORB: (0) Close remaining strands.
omniORB: (0) 0 remaining bidir ropes deleted.
omniORB: (0) 0 remaining ropes deleted.
omniORB: (0) Clear endPoint options.
omniORB: (0) AsyncInvoker: deleted.
OrbWrapper::cleanup() done
omniORB: (0) No more references to the ORB -- deleted.
OrbWrapper::createInstance() = 0 done
Orb initialization failed.
omniORB: (0) Final clean-up
omniORB: (0) Deleted 2 nil object references and 0 other tracked objects.
omniORB: (0) Final clean-up completed.
==19179==
==19179== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 5 from 1)
==19179== malloc/free: in use at exit: 568 bytes in 2 blocks.
==19179== malloc/free: 428 allocs, 426 frees, 51,288 bytes allocated.
==19179== For counts of detected errors, rerun with: -v
==19179== searching for pointers to 2 not-freed blocks.
==19179== checked 168,492 bytes.
==19179==
==19179== 156 bytes in 1 blocks are still reachable in loss record 1 of 2
==19179== at 0x4024A4E: operator new(unsigned int)
(vg_replace_malloc.c:224)
==19179== by 0x4117812: omni::giopServer::singleton()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x4119E33:
omni::registerGiopServer(omni::omniInterceptors::createORBServer_T::info_T&)
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40CA850: omni::omniObjAdapter::initialise()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40EEB48: initialise_poa()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40EF883: omni::omniOrbPOA::rootPOA(int)
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40EF8F3: omni::resolveRootPOAFn()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40B5A08: omni::omniInitialReferences::resolve(char const*,
unsigned int) (in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x409FAE9: omniOrbORB::resolve_initial_references(char const*)
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x804AB6E: OrbWrapper::createInstance(char const*, char
const*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
(OrbWrapper.cc:224)
==19179== by 0x8049BF2: main (Main.cc:82)
==19179==
==19179==
==19179== 412 bytes in 1 blocks are still reachable in loss record 2 of 2
==19179== at 0x402436E: operator new[](unsigned int)
(vg_replace_malloc.c:268)
==19179== by 0x4117732: omni::giopServer::giopServer()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x411781C: omni::giopServer::singleton()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x4119E33:
omni::registerGiopServer(omni::omniInterceptors::createORBServer_T::info_T&)
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40CA850: omni::omniObjAdapter::initialise()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40EEB48: initialise_poa()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40EF883: omni::omniOrbPOA::rootPOA(int)
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40EF8F3: omni::resolveRootPOAFn()
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x40B5A08: omni::omniInitialReferences::resolve(char const*,
unsigned int) (in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x409FAE9: omniOrbORB::resolve_initial_references(char const*)
(in /usr/local/gcc-3.4.6/omni-4.1.4/lib/libomniORB4.so.1.4)
==19179== by 0x804AB6E: OrbWrapper::createInstance(char const*, char
const*, unsigned int, unsigned int, unsigned int, unsigned int, unsigned int)
(OrbWrapper.cc:224)
==19179== by 0x8049BF2: main (Main.cc:82)
==19179==
==19179== LEAK SUMMARY:
==19179== definitely lost: 0 bytes in 0 blocks.
==19179== possibly lost: 0 bytes in 0 blocks.
==19179== still reachable: 568 bytes in 2 blocks.
==19179== suppressed: 0 bytes in 0 blocks.

In order to reproduce the problem please compile and run the attached program
via the runOrbTest start script (perhaps the LD_LIBRARY_PATH and/or the path
to valgrind has to be changed) in two different shell windows. The program
instance which is started first will use port 50000. After initializing the
orb the program will sleep for 20 seconds and then terminate. This program
instance shows no leaks. If a second program instance is started during the
20 seconds period it will fail to bind the port 50000 and then terminate. Its
the second program instance which shows the leak above.

Best regards,
Martin
-------------- next part --------------
A non-text attachment was scrubbed...
Name: orb.tgz
Type: application/x-tgz
Size: 5198 bytes
Desc: not available
Url : http://www.omniorb-support.com/pipermail/omniorb-list/attachments/20090902/53b58bf4/orb.bin
Bruce Visscher
2009-09-02 23:35:57 UTC
Permalink
Martin,

I am not sure that what you are trying to do is valid.? Specifically,
the ORB is a singleton so I do know that initializing the ORB, using
it, shutting it down then starting it back up is not allowed.

In your case, since the initialization exits via exception I suppose
it could be argued that the initialization is not complete so perhaps
it should "roll back" and this should be allowed.? I would be curious
to know whether this is required to work by the CORBA standard (okay,
I was too lazy to check myself).

On the other hand, I don't really understand what you are trying to
accomplish.? I would expect that either you let the system allocate a
port for you and somehow make available any resulting object reference
(for example by using omninames or some other CosNaming service
implementation) or else you would have the system reserve a specific
port for your server and make your object references persistent using
the given port number.? I don't see where the third option that you
propose of trying to allocate a port by trial and error within a
certain range would be useful.? (It also occurs to me that if you
really want to do this just let the program exit via exception and
move the for loop out to the shell...)

Bruce
Göttlicher, Dr.-Ing Martin
2009-09-03 13:58:38 UTC
Permalink
Hello Bruce,

thanks for your answer. Unfortunately I have to use the endpoint
initialization. I have to workaround a bug in a component which I don't have
under my control and I can only use a very limited number of ports. I also
don't know if it is valid to shutdown and restart an ORB according to the
CORBA standard, but nevertheless I think it should be possible to terminate
an application without leaks in case of an initialization failure (the memory
leak is there even if you don't try another initialization).

Best regards,
Martin
Bruce Visscher
2009-09-03 20:56:12 UTC
Permalink
Post by Göttlicher, Dr.-Ing Martin
I also
don't know if it is valid to shutdown and restart an ORB according to the
CORBA standard,
To be clear, this is not valid. The ORB is a singleton and cannot be
reinitialized. What I was talking about was whether it was legal to
retry CORBA::ORB_init if it exits via exception.
Post by Göttlicher, Dr.-Ing Martin
but nevertheless I think it should be possible to terminate
an application without leaks in case of an initialization failure (the memory
leak is there even if you don't try another initialization).
If you truly terminate the application then you don't have to worry
about leaks. Then you could pass in the port from the shell in a
loop. This might be your only option.
Duncan Grisby
2009-09-03 21:41:44 UTC
Permalink
Post by Göttlicher, Dr.-Ing Martin
in a project I have to use an endpoint to initialize the ORB. If the
initialization is successful everything is fine. If the initialization fails
(because the port is already occupied) memory is leaked as shown by the
It's a bug. The trivial fix is to remove the line that says

if( !initialised ) return;

at line 504 of src/lib/omniORB/orbcore/objectAdapter.cc

I'll check in that fix.

[...]
Post by Göttlicher, Dr.-Ing Martin
In order to reproduce the problem please compile and run the attached program
via the runOrbTest start script (perhaps the LD_LIBRARY_PATH and/or the path
to valgrind has to be changed) in two different shell windows. The program
instance which is started first will use port 50000. After initializing the
orb the program will sleep for 20 seconds and then terminate. This program
instance shows no leaks. If a second program instance is started during the
20 seconds period it will fail to bind the port 50000 and then terminate. Its
the second program instance which shows the leak above.
I had a very brief look at your code before deciding that it was complex
enough that it was simpler to just reproduce your issue with the omniORB
echo examples. However, in my brief look, I did notice that you have
some functions that return _var types. That's always a bad idea, because
it confuses the memory management rules. You should always return _ptr
types and assign the results to _vars.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Duncan Grisby
2009-09-03 21:52:56 UTC
Permalink
Post by Bruce Visscher
Post by Göttlicher, Dr.-Ing Martin
I also
don't know if it is valid to shutdown and restart an ORB according to the
CORBA standard,
To be clear, this is not valid. The ORB is a singleton and cannot be
reinitialized. What I was talking about was whether it was legal to
retry CORBA::ORB_init if it exits via exception.
Actually, it is valid. As long as orb->destroy() is called, it's valid
to do ORB_init again.

Cheers,

Duncan.
--
-- Duncan Grisby --
-- ***@grisby.org --
-- http://www.grisby.org --
Loading...