RE: Is this a memory leak?
"Hwang, Johnny" <[email protected]> Mon, 24 Sep 2012 06:22:10 +0000
| Newsgroups | gmane.network.open-pegasus.general |
|---|---|
| Message-ID | <59187A369D10D048A8A8B52B1BD1FEA50D2C939B@SACEXCMBX02-PRD.hq.netapp.com> |
Hello all, I have retrieved all the information I could and can conclusively conclude (as far as I understand) that there is no memory leak in that part of the pegasus code. Just a reminder to all developers: If you have a provider that contains an active thread that runs in a loop that directly or indirectly allocates memory from CMPI and/or calls helper functions that directly or indirectly allocates memory from CMPI, all those memory must be explicitly allocated. Example calls: newInstance() getKey() [if the return value is a CMPIString, CMPI_ref, etc., something other than numbers] toString() getClassName() In addition to clone(), which is a known (explicit) memory allocator. Could I also get a complete list of implicit memory allocators, so that I know which functions to watch out for as potential memory leaks? Thanks, Johnny From: Hwang, Johnny Sent: Sunday, September 23, 2012 11:17 AM To: [email protected]; Hwang, Johnny Cc: [email protected] Subject: Re: Is this a memory leak? Hmm I am calling release() on the instance with which I called deliverIndication(). The leak trace is not pointing to newInstance(), but to deliverInstance(). I'll try to get more information on this. Sent via the Samsung Galaxy S(tm)III, an AT&T 4G LTE smartphone Marek Szermutzky <[email protected]<mailto:[email protected]>> wrote: This is not a memory leak. Please let me explain why and where the memory is released. The object holding the memory created through _rep = new CIMInstanceRep() is CIMInstance indInst; That object is placed on the stack, meaning on leaving function mbDeliverIndication() in CMPIBroker.cpp the destructor of it is called. The destructor of CIMInstance does call Dec(_rep) which is inherited from class CIMObjectRep. void Dec() { if (_refCounter.decAndTestIfZero()) delete this; } and here the internal representation of object CIMInstanceRep is deleted. If you see memory growing on indication providers, a common mistake made by CMPI provider writers is not to release instances delivered while delivering instances through a separate thread created by the provider for that purpose. Calling CMReleaseInstance() after each CMDeliverInstance() will help the CIM Server to release that memory early. Mit freundlichen Grüßen / Kind regards Marek Szermutzky Software Engineer / OpenPegasus Maintainer (PMC) and z/OS PlatformRep. IBM Systems &Technology Group, Systems Software Development / z/OS Capacity Management and Support ------------------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Schoenaicher Str. 220 71032 Boeblingen Phone: +49-7031-16-5182 E-Mail: [email protected]<mailto:[email protected]> ------------------------------------------------------------------------------------------------------------------------------------------- IBM Deutschland Research & Development GmbH / Vorsitzender des Aufsichtsrats: Martin Jetter Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen / Registergericht: Amtsgericht Stuttgart, HRB 243294 From: "Hwang, Johnny" <[email protected]<mailto:[email protected]>> To: "[email protected]<mailto:[email protected]>" <[email protected]<mailto:[email protected]>> Date: 19.09.2012 10:07 Subject: Is this a memory leak? ________________________________ This is in src/Pegasus/ProviderManager2/CMPI/CMPI_Broker.cpp, circa line 900. static CMPIStatus mbDeliverIndication( const CMPIBroker* eMb, const CMPIContext* ctx, const char *ns, const CMPIInstance* ind) { PEG_METHOD_ENTER( TRC_CMPIPROVIDERINTERFACE, "CMPI_Broker:mbDeliverIndication()"); // If no valid broker was passed in we try the use the broker // that was stored in the local thread context if (eMb==NULL) { eMb = CM_BROKER; } CMPI_Broker *mb = (CMPI_Broker*)eMb; IndProvRecord *indProvRec; OperationContext* context = CM_Context(ctx); SCMOInstance* scmoInst = SCMO_Instance(ind); CIMInstance indInst; scmoInst->getCIMInstance(indInst); //*** <- IS THIS A MEMORY LEAK?!?!? Does this guy need to be freed explicitly? getCIMInstance() calls new() in its stack.*** ... PEG_METHOD_EXIT(); CMReturn(CMPI_RC_ERR_FAILED); } } This is my valgrind feed: > ==14407== 71,088 bytes in 1,481 blocks are possibly lost in loss record 4,369 of 4,489 > ==14407== at 0x4C710D5: operator new(unsigned int) (vg_replace_malloc.c:214) > ==14407== by 0x7A65AAE: Pegasus::CIMInstanceRep::clone() const (CIMInstanceRep.h:64) > ==14407== by 0x7A81101: Pegasus::CIMObject::clone() const (CIMObject.cpp:229) > ==14407== by 0x7AA5A0F: Pegasus::CIMValue::set(Pegasus::CIMObject const&) (CIMValue.cpp:797) > ==14407== by 0x7A22575: Pegasus::SCMOInstance::_getCIMValueFromSCMBUnion(Pegasus::CIMValue&, Pegasus::CIMType, bool, bool, unsigned int, Pegasus::SCMBUnion const&, char const*) (SCMO.cpp:2175) > ==14407== by 0x7A22919: Pegasus::SCMOInstance::_getCIMValueFromSCMBValue(Pegasus::CIMValue&, Pegasus::SCMBValue const&, char const*) (SCMO.cpp:2244) > ==14407== by 0x7A22BEC: Pegasus::SCMOInstance::_getCIMPropertyAtNodeIndex(unsigned int) const (SCMO.cpp:1747) > ==14407== by 0x7A23B1A: Pegasus::SCMOInstance::getCIMInstance(Pegasus::CIMInstance&) const (SCMO.cpp:1633) > ==14407== by 0xC0CE632: mbDeliverIndication (CMPI_Broker.cpp:928) > ==14407== by 0xC12BD14: sendIndicationFunction (x.c:x)<- this line reads "pBrk->bft->deliverIndication(pBrk, pCtx, pNamespace,...)" > ==14407== I have nowhere near 1481 indication items to process. More in the order of low hundreds, run for several cycles. Therefore, this is not an individual cycle, but continuously piled up over time and is most likely a leak. Thanks for understanding, Johnny Hwang