Print

Print


Hi Andrew,

I think I found the leak. Consider how XrdSsiTaskReal objects are 
managed. They are allocated here:

XrdSsiSessReal.cc:260       else {if (!alocLeft || !(tP = new 
XrdSsiTaskReal(this, nextTID)))

and released through RelTask in two places(???):
// from RequestFinished()
XrdSsiSessReal.cc:116   if (rtP->Kill()) RelTask(rtP);
// As a result of an error in ProcessRequest()
XrdSsiSessReal.cc:294       RelTask(tP);
// As a result of Recycle()
XrdSsiSessRea.cc:324       RelTask(tP);

I think we are primarily concerned with the RelTask as a result of 
RequestFinished(), which happens for every Finished() call, as long as 
theSession is non-null. I can verify that for every ProcessRequest() 
that I call, there is a Finished() call.

The problem is that if stopping is false, RelTask does not delete the 
task (stored as tP):
----
void XrdSsiSessReal::RelTask(XrdSsiTaskReal *tP) // myMutex locked!
{

// Delete this task or place it on the free list
//
    DBG("RelTask dodel="<<stopping<<" id="<<tP->ID());
    if (stopping) delete tP;
       else {tP->attList.next = freeTask;
             freeTask = tP;
            }
}
----
I can verify that stopping is false on every call because I have 
messages that say: "RelTask dodel=0 id=0". My guess is that deletion is 
deferred until stopping is true, which only happens on Unprovision(). 
When Unprovision is called, it calls Detach() on each element in the 
(ad-hoc?) linked list chain of tP->attList.next .
But XrdSsiTaskReal::Detach() doesn't seem to do anything but set tStat 
to isDead, which only seems to matter if 
XrdSsiTaskReal::HandleResponse() is called, and I don't see why it would 
get called, because no more responses should get triggered for this 
particular session, because we are in an XrdSsiSessReal::Unprovision call.

Does this sound plausible? I'm trying to infer what I can from the code, 
but I think you meant for this deferred-deletion mechanism to be 
something clients should never worry about--I didn't find any design 
notes for it.

-Daniel

On 05/08/2014 10:15 PM, Andrew Hanushevsky wrote:
> Hi Daniel,
>
> I can't see anything wrong. So, you should put in the old print statements
> where you allocate and delete (also indicate how much you allocated). Then
> we can see if you are indeed doing what you think you are doing. I can do
> that as well if you give me the stuff that compiles and create the
> appropriate shared library.
>
> Andy
>
> On Thu, 8 May 2014, Daniel L. Wang wrote:
>
>> Hi Andy,
>>
>> I'm trying to make sure that I don't leak memory using the client interface,
>> but I still end up leaking about 100 bytes for each sequence of
>> getservice-provision-request-close-cleanup. I seem to be failing to release
>> memory in 2 places. Here's a valgrind report for 30 iterations of the
>> sequence.
>>
>> ==13424== 450 bytes in 30 blocks are definitely lost in loss record 7 of 8
>> ==13424==    at 0x4A07152: operator new[](unsigned long)
>> (vg_replace_malloc.c:363)
>> ==13424==    by 0x401C92: (anonymous
>> namespace)::MyRequest::MyRequest(XrdSsiSession*) (myclient.cc:30)
>> ==13424==    by 0x402693: (anonymous namespace)::MyResource::makeRequest()
>> (myclient.cc:177)
>> ==13424==    by 0x40263F: (anonymous
>> namespace)::MyResource::ProvisionDone(XrdSsiSession*) (myclient.cc:171)
>> ==13424==    by 0x4C279C9:
>> XrdSsiSessReal::HandleResponse(XrdCl::XRootDStatus*, XrdCl::AnyObject*)
>> (XrdSsiSessReal.cc:157)
>> ==13424==    by 0x4C26C69:
>> XrdCl::ResponseHandler::HandleResponseWithHosts(XrdCl::XRootDStatus*,
>> XrdCl::AnyObject*, std::vector<XrdCl::HostInfo,
>> std::allocator<XrdCl::HostInfo> >*) (XrdClXRootDResponses.hh:850)
>> ==13424==    by 0x4F47693: (anonymous
>> namespace)::OpenHandler::HandleResponseWithHosts(XrdCl::XRootDStatus*,
>> XrdCl::AnyObject*, std::vector<XrdCl::HostInfo,
>> std::allocator<XrdCl::HostInfo> >*) (XrdClFileStateHandler.cc:86)
>> ==13424==    by 0x4F3AEDF: XrdCl::XRootDMsgHandler::HandleResponse()
>> (XrdClXRootDMsgHandler.cc:1008)
>> ==13424==    by 0x4F38204: XrdCl::XRootDMsgHandler::Process(XrdCl::Message*)
>> (XrdClXRootDMsgHandler.cc:300)
>> ==13424==    by 0x4F198D1: XrdCl::Stream::HandleIncMsgJob::Run(void*)
>> (XrdClStream.hh:279)
>> ==13424==    by 0x4F6FFED: XrdCl::JobManager::RunJobs()
>> (XrdClJobManager.cc:148)
>> ==13424==    by 0x4F6FB37: RunRunnerThread (XrdClJobManager.cc:33)
>> ==13424==
>> ==13424== 3,360 bytes in 30 blocks are definitely lost in loss record 8 of 8
>> ==13424==    at 0x4A075BC: operator new(unsigned long)
>> (vg_replace_malloc.c:298)
>> ==13424==    by 0x4C27F8C: XrdSsiSessReal::ProcessRequest(XrdSsiRequest*,
>> unsigned short) (XrdSsiSessReal.cc:260)
>> ==13424==    by 0x4026DC: (anonymous namespace)::MyResource::makeRequest()
>> (myclient.cc:179)
>> ==13424==    by 0x40263F: (anonymous
>> namespace)::MyResource::ProvisionDone(XrdSsiSession*) (myclient.cc:171)
>> ==13424==    by 0x4C279C9:
>> XrdSsiSessReal::HandleResponse(XrdCl::XRootDStatus*, XrdCl::AnyObject*)
>> (XrdSsiSessReal.cc:157)
>> ==13424==    by 0x4C26C69:
>> XrdCl::ResponseHandler::HandleResponseWithHosts(XrdCl::XRootDStatus*,
>> XrdCl::AnyObject*, std::vector<XrdCl::HostInfo,
>> std::allocator<XrdCl::HostInfo> >*) (XrdClXRootDResponses.hh:850)
>> ==13424==    by 0x4F47693: (anonymous
>> namespace)::OpenHandler::HandleResponseWithHosts(XrdCl::XRootDStatus*,
>> XrdCl::AnyObject*, std::vector<XrdCl::HostInfo,
>> std::allocator<XrdCl::HostInfo> >*) (XrdClFileStateHandler.cc:86)
>> ==13424==    by 0x4F3AEDF: XrdCl::XRootDMsgHandler::HandleResponse()
>> (XrdClXRootDMsgHandler.cc:1008)
>> ==13424==    by 0x4F38204: XrdCl::XRootDMsgHandler::Process(XrdCl::Message*)
>> (XrdClXRootDMsgHandler.cc:300)
>> ==13424==    by 0x4F198D1: XrdCl::Stream::HandleIncMsgJob::Run(void*)
>> (XrdClStream.hh:279)
>> ==13424==    by 0x4F6FFED: XrdCl::JobManager::RunJobs()
>> (XrdClJobManager.cc:148)
>> ==13424==    by 0x4F6FB37: RunRunnerThread (XrdClJobManager.cc:33)
>>
>> Is there something that sticks out at you? Code attached.
>>
>> Thanks,
>> -Daniel
>>
>>

########################################################################
Use REPLY-ALL to reply to list

To unsubscribe from the QSERV-L list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=QSERV-L&A=1