none
Strange connection behaviour. (memory leak)(need help) RRS feed

  • Question

  • I have written a polling component that connects to a sybase database every 5 seconds and then executes a stored procedure.
    This polling component is a BizTalk Adapter but that doesn't matter for the problem that I encounter.
     
    To connect to the Sybase Database I use two DLL's that come with sybase, they are :
    • Sybase.Data.AseClient.dll
    • sybdrvado115.dll
    The problem.
     
    De polling component works fine and there are absolutely no signs of a memory leak. After running for several days memroy consumtion is still low.
    Then all of a sudden there is something wrong with the Unix Server and it is no longer possible to create a connection to the Sybase Server hosted on the Unix machine.
     
    The error I get is the following :
     
    Event Type: Warning
    Event Source: BizTalk Server 2006
    Event Category: BizTalk Server 2006
    Event ID: 5740
    Date:  3-11-2009
    Time:  14:45:35
    User:  N/A
    Computer: 
    Description:XXXXXXXX
    The adapter "SybaseStoredProcedure" raised an error message. Details "Client unable to establish a connection".
    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
     
    From that moment on there is a memory leak on each poll. So I went to my Development server and tried to enter an invalid Machine name to get the same error message.
     
    Event Type: Warning
    Event Source: BizTalk Server 2006
    Event Category: BizTalk Server 2006
    Event ID: 5740
    Date:  11/5/2009
    Time:  9:13:32 AM
    User:  N/A
    Computer: YYYYYYYY
    Description:
    The adapter "SybaseStoredProcedure" raised an error message. Details "Client unable to establish a connection".
    For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.

    So I have exactly the same error message on my developement machine but this time there is NO memory leak at all.

    So the real question is....
     
    Does anybody have a clou why a memory leak can exist in this situation.
     
    I have been thinking about several options
    - The sybase components do some caching and once a connection has been made, it will return that same connection every time.
      ( if the connection is broken later on the sybase components don't pick it up ? )
    - The polling component is unable to connect to the Sybase adapter unless it's host process (host process of polling component = BizTalk) is restarted.....
     
    The code that gets executed on every poll is the following :
     
            public void SubmitBatch()
            {
                int nrOfMessages = 0;
                try
                {
                    this.receivingData = true;
    
                    //  used to block the Terminate from BizTalk 
                    if (!this.control.Enter())
                    {
                        return;
                    }
    
                    SyncReceiveSubmitBatch batch = null;
    
                    while (nrOfMessages < properties.ReceiveBatchSize && !control.TerminateCalled)
                    {
                        MemoryStream newMsgStream = null;
    
                        // Now try to recieve data 
                        using (AseConnection conn = currentHelper.BuildConnection(connectionParameters))
                        {
                            conn.Open();
                            if (connectionParameters.TransactionLevel != System.Data.IsolationLevel.Unspecified)
                            {
                                AseTransaction trans = conn.BeginTransaction(connectionParameters.TransactionLevel);
                            }
                            using (AseCommand cmd = currentHelper.BuildCommandObject(connectionParameters, conn))
                            {
                                using (DataTable resultParameters = currentHelper.GenerateParameterDatatable(connectionParameters))
                                {
                                    DataSet ds = new DataSet("PRC_" + connectionParameters.ProcedureName);
                                    AseDataAdapter da = new AseDataAdapter(cmd);
                                    da.Fill(ds, "PRC_ROWS_" + connectionParameters.ProcedureName);
                                    currentHelper.ResultParametersToTable(ds, resultParameters, cmd);
                                    if (ds.Tables["PRC_ROWS_" + connectionParameters.ProcedureName].Rows.Count > 0)
                                    {
                                        // Data was found write the data to the stream...
                                        newMsgStream = new MemoryStream();
                                        ds.WriteXml(newMsgStream);
                                        newMsgStream.Position = 0;
                                    }
                                    if (connectionParameters.TransactionLevel != System.Data.IsolationLevel.Unspecified)
                                    {
                                        conn.Transaction.Commit();
                                    }
                                    da.Dispose();
                                    ds.Dispose();
                                }
                            }
                            if (conn.State != ConnectionState.Closed)
                            {
                                conn.Close();
                            }
                        }
                        if (newMsgStream == null)
                        {
                            break; // We might not have reached the batchsize yet but we don't want to wait for that.
                        }
                        else
                        {
                            newMsgStream.Flush();
                            newMsgStream.Seek(0, SeekOrigin.Begin);
                            IBaseMessage btsMsg = CreateMessage(newMsgStream);
                            if (batch == null)
                            {
                                //Create a new batch when this is the first message
                                batch = new SyncReceiveSubmitBatch(this.transportProxy, this.control, 1);
                            }
                            if (properties.IsTwoWay)
                            {
                                // Put your reponse handler code here, if needed.
    
                            }
                            else
                            {
                                // batch.SubmitMessage(btsMsg, new StreamAndUserData(btsMsg.BodyPart.Data, newMsgStream));
                                batch.SubmitMessage(btsMsg);
                            }
                            nrOfMessages++;
                        }
    
                    }//end while
                    if (nrOfMessages != 0)
                    {
                        batch.Done();
                    }
                }
                catch (Exception e)
                {
                    this.transportProxy.SetErrorInfo(e);
                }
                finally
                {
                    this.control.Leave();
                }
                receivingData = false;
            }
    

     


    Well0549
    Thursday, November 5, 2009 8:56 AM

Answers

  • First you could try to profile code execution to see if you can collect more useful information about it. I personally use profiler from Redgate that help to identify memory leaks, but you could find some other tools that help you with memory profiling. If leak coming from that unmanaged DLL, I do not think you could do anything with it except properly catch all the exceptions and dispose all the .NET objects that might use that DLL. The reason you cannot do much is because you do not instantiate anything directly from that DLL and do not have any control, so the only way to clean up is from inside of the .NET code that instantiated that unmanaged code. BUT, it will work ONLY in a case if .NET code properly implements Dispose methods. My guess this is not done properly inside of the provider. Did you try to contact Sybase to see if they have any patch for the issue?


    Val Mazur (MVP) http://www.xporttools.net
    Monday, November 9, 2009 11:11 AM
    Moderator
  • I found the solution.

    Using the newest drivers from sybase...

    Sybase.AdoNet2.AseClient.dll
    sybdrvado20.dll

    Solves the problem !

    Thanks everyone for the help.
    Well0549
    Thursday, November 26, 2009 9:22 AM

All replies

  • Hi,

     

    Welcome to ADO.NET Data Providers forum!

     

    Since you are using some third party database via third party dlls, it is really hard for us to troubleshoot where the problem is.  From a quick research on your code snippet, I don’t find any apparent problems on memory leak.  I strongly recommend you consult this issue with the Sybase supporting channels.  

     

    Have a nice weekend!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Friday, November 6, 2009 3:43 AM
    Moderator
  • Hi Well0549,

    If you look at your code, you see the following two lines:
        DataSet ds = new DataSet("PRC_" + connectionParameters.ProcedureName);
        AseDataAdapter da = new AseDataAdapter(cmd);

    Both are disposable objects that are only properly disposed when there are no exceptions. Adding using statements for these two objects will ensure they are disposed when there are exceptions.

    Another, not that obvious disposable object, is the MemoryStream object: http://msdn.microsoft.com/en-us/library/system.io.memorystream.aspx. I can't see that you dispose of that object.

    Hope this helps. If not, you where to reach me

    Jan aka SCHR0157
    • Proposed as answer by Jan Schreuder Friday, November 6, 2009 7:02 AM
    Friday, November 6, 2009 6:57 AM
  • Hi Jan,

    Well I agree with you but since the Connection.Open throws an exception, I think the code doesn't get to that point......

    Cause i ran my adapter with a faulty server name ( this triggers exactly the same error ) and no memory eting was happening. It seems the ADO / Sybase stuff gets lost when the connection was established and later on is no longer available....

    Normally this memory leak wouldn't really matter but my adapter will try over and over to make a connection, that is when the leaking happens....
    Well0549
    Friday, November 6, 2009 9:02 AM
  • Keep in mind that sybdrvado115.dll file is not .NET managed code and the memory allocated by that DLL will not be automatically collected by GC in a case of error. I think this is the root of the leak.
    Val Mazur (MVP) http://www.xporttools.net
    Friday, November 6, 2009 11:16 AM
    Moderator
  • I guess that's 100% true.... Any suggestions how to solve this ?
    Well0549
    Friday, November 6, 2009 3:01 PM
  • First you could try to profile code execution to see if you can collect more useful information about it. I personally use profiler from Redgate that help to identify memory leaks, but you could find some other tools that help you with memory profiling. If leak coming from that unmanaged DLL, I do not think you could do anything with it except properly catch all the exceptions and dispose all the .NET objects that might use that DLL. The reason you cannot do much is because you do not instantiate anything directly from that DLL and do not have any control, so the only way to clean up is from inside of the .NET code that instantiated that unmanaged code. BUT, it will work ONLY in a case if .NET code properly implements Dispose methods. My guess this is not done properly inside of the provider. Did you try to contact Sybase to see if they have any patch for the issue?


    Val Mazur (MVP) http://www.xporttools.net
    Monday, November 9, 2009 11:11 AM
    Moderator
  • No i did not try to contact Sybase

    Thanks for your input !
    Well0549
    Monday, November 9, 2009 2:49 PM
  • First of all....

    I unmarked ALL ANSWERS FROM VMAZUR as an answer...

    It's MY QUESTION AND I DECIDE IF IT IS ANSWERED !

    And NO it has not been answered at all....

    I do have some new findings however...

    1. If I enter a faulty server name in the connection string there is no leak.
    2. If I enter the correct servername but mess up my host file making the servername point to a nonexistend IP I do get the leak.

    So probably it's buried very deep anybody any idea ?
    Well0549
    Thursday, November 12, 2009 8:14 AM
  • Hi,

     

    Sorry for marking the answer in advance.  I think VMazur has provided the troubleshooting method.  Also, if the memory leak is inside the DLLs, I don’t think we can fix it only by .NET managed codes. 

     

    I strongly recommend follow VMazur’s suggestion to use Profiler to check where the memory leak is.  This information is quite important for us to figure out how to fix it. 

     

    If the problem is caused by the third party DLLs, I suggest you consult the Sybase support channel for this issue. 

     

    Have a nice day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, November 12, 2009 9:18 AM
    Moderator
  • Did you try to profile the code? I would not expect to get an answer to the problem here, since .NET code looks fine. To me (I could be wrong) it goes deep to the provider level and Sybase would be the best source of information in this case.


    Val Mazur (MVP) http://www.xporttools.net
    Thursday, November 12, 2009 11:06 AM
    Moderator
  • Hi,

     

    How is the problem now?   Have tried the Visual Studio profiler?   If you need any further assistance, please feel free to let me know.

     

    Have a nice day!

     

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, November 19, 2009 12:25 AM
    Moderator
  • We are changing the issue type to “General Discussion” because you have not followed up with the necessary information. If you have more time to look at the issue and provide more information, please feel free to change the issue type back to “Question” by opening the Options list at the top of the post window, and changing the type. If the issue is resolved, we will appreciate it if you can share the solution so that the answer can be found and used by other community members having similar questions.

    Thank you!


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Thursday, November 26, 2009 12:35 AM
    Moderator
  • I found the solution.

    Using the newest drivers from sybase...

    Sybase.AdoNet2.AseClient.dll
    sybdrvado20.dll

    Solves the problem !

    Thanks everyone for the help.
    Well0549
    Thursday, November 26, 2009 9:22 AM

  • Thank you very much for sharing the solution.

    Have a nice day!

     

    Best Regards,
    Lingzhi Sun

    MSDN Subscriber Support in Forum

    If you have any feedback on our support, please contact msdnmg@microsoft.com


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Tuesday, December 1, 2009 8:44 AM
    Moderator