cancel
Showing results for 
Search instead for 
Did you mean: 

How to I prevent AppDomain.Unload() from hanging on SAP's ADO.NET finalizer?

Former Member
4,098

We have a problem in our test runs that use Sap.Data.SQLAnywhere. The test run never finishes.

Each test case finishes, but the vstest.console execution never finishes because it's waiting on an instance of Sap.Data.SQLAnywhere.SAUnmanagedDll's finalizer.

Here's a C# repro, as far as I can narrow it down:

using System;
using System.Data.Common;

class Repro : MarshalByRefObject
{
    public string Get()
    {
        using (var connection = DbProviderFactories.GetFactory("Sap.Data.SQLAnywhere").CreateConnection())
        {
            Console.WriteLine(connection.GetType().Assembly.FullName);

            connection.ConnectionString = "Host=MyServer;DatabaseName=Northwind;Integrated=True";
            //TODO Uncomment connection.ConnectionString += ";Pooling=False";

            connection.Open();
        }

        return "DONE";
    }

    public static void Main(string[] args)
    {
        AppDomainSetup newSetupInfo = new AppDomainSetup
        {
            ApplicationBase = typeof(Repro).Assembly.Location
        };

        AppDomain testDomain = null;
        try
        {
            testDomain = AppDomain.CreateDomain("TestDomain");

            Repro remoteObj = (Repro)testDomain.CreateInstance(
                typeof(Repro).Assembly.FullName,
                typeof(Repro).FullName).Unwrap();

            Console.WriteLine("BEFORE TEST");
            remoteObj.Get();
            Console.WriteLine("AFTER TEST");
        }
        finally
        {
            if (testDomain != null)
            {
                Console.WriteLine("BEFORE UNLOAD");
                AppDomain.Unload(testDomain);
                Console.WriteLine("AFTER UNLOAD");
            }
        }
    }
}

If you compile and run this against .NET 3.5, it prints "BEFORE UNLOAD" but then hangs at the call to AppDomain.Unload().

If I pause in the managed debugger, the .NET finalizer thread has made an unmanaged call at Sap.Data.SQLAnywhere.v3.5.dll!Sap.Data.SQLAnywhere.SAUnmanagedDll.Finalize(). For whatever reason, this call hanging is blocking the finalizer thread.

In the unmanaged debugger, the call stack is:

ntdll.dll!_RtlEnterCriticalSection@4\x1e() Unknown
dbdata17.dll!0f49918f() Unknown
[Frames below may be incorrect and/or missing, no symbols loaded for dbdata17.dll]  
dbdata17.dll!0f49a22c() Unknown
dbdata17.dll!0f498d18() Unknown
dbdata17.dll!0f49c037() Unknown
[Managed to Native Transition]  
Sap.Data.SQLAnywhere.v3.5.dll!<Unknown function>    Unknown

(If you uncomment the //TODO to disable connection pooling, then Unload() is instant.)

My version of Sap.Data.SQLAnywhere is Sap.Data.SQLAnywhere.v3.5, Version=17.0.0.10623

It also (hangs on both .NET 4.5, which loads Sap.Data.SQLAnywhere.v4.5, Version=17.0.0.10624 )

Is this a bug in Sap.Data.SQLAnywhere? Is there a way to fix the finalizer hang without disabling connection pooling? Is there some other workaround that would prevent the Unload() hang ?

Accepted Solutions (1)

Accepted Solutions (1)

jeff_albion
Product and Topic Expert
Product and Topic Expert

Update: This issue has been fixed as of 17.0.0.1298 and will be released in upcoming support packages.


Thanks for the concise reproducible - I can also reproduce this using a blank database, without Integrated Logins enabled:

dbinit -dba dba,sql -mpl 3 demo17.db
dbsrv17 demo17.db

connection.ConnectionString = "uid=dba;pwd=sql;server=demo17";

I also can confirm that it seems that disabling connection pooling changes the hang behaviour - I would recommend using that workaround until we can better understand the interaction and provide a fix.

I have opened CR #791082 to investigate further.

Answers (1)

Answers (1)

Former Member
0 Kudos

I don't know what difference pooling=true or pooling=false could make since connection pooling really doesn't pool integrated logins in the current implementation and the pooling implmentation should be independent of the unmanaged code where the hang seems to be occuring.

So if disabling connection pooling would be a viable interim solution to this issue until it can be investigated in more detail. {... at which point I would recommend opening up a support incident and provide your example code and database for review...}

I did notice you do not have a catch block in the main part of your code, so might this have something to do with an unhandled exception and side-effects from that maybe? Also if there is something special around the way you have your integrated logins set up and mapped, that may be important to know.

There have been some recent corrections made to our integrated login support around group membership but I don't recognize this as being a matching symptom of any of that.

Either way the fact that pooling is playing any role in any of this seems very odd and unexpected.

HTH

Former Member
0 Kudos

As @Jeff points out, this also reproduces with username and password auth, and in both cases turning off pooling fixes the problem.