[Mono-bugs] [Bug 497919] New: System.Data.SqlClient.SqlConnection.Open() never returns (hangs) if host is unavailable. Behaves different than .NET

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Fri Apr 24 05:58:37 EDT 2009


http://bugzilla.novell.com/show_bug.cgi?id=497919


           Summary: System.Data.SqlClient.SqlConnection.Open() never
                    returns (hangs) if host is unavailable. Behaves
                    different than .NET
    Classification: Mono
           Product: Mono: Class Libraries
           Version: 2.4.x
          Platform: i686
        OS/Version: Ubuntu
            Status: NEW
          Severity: Critical
          Priority: P5 - None
         Component: Sys.Data.SqlClient
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: jonas.larsson at manodo.se
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


User-Agent:       Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.9)
Gecko/2009042113 Ubuntu/9.04 (jaunty) Firefox/3.0.9

If the host given in connection string can't be connected to
SqlConnection.Open() never returns. You can wait forever for it. The behaviour
is different than in .NET.
Using 2.4 release tarball.


(I'm aware of Bug 413439 - Connection Pooling Don't Work Properly. It's related
but not the same so i'm creating a new bug report)

Example program/testcase:

-------------------

using System;
using System.Data.SqlClient;
using System.Threading;

static class Program
{
  static AutoResetEvent statusevent = new AutoResetEvent(false);

  static void Main()
  {
    string connstr = "Data Source=nonExistingHost.dummyDomain;Initial
Catalog=myDataBase;User Id=myUsername;Password=myPassword;Connection
Timeout=10";
    SqlConnection connection = new SqlConnection(connstr);
    DateTime startTime = DateTime.Now;
    TimeSpan elapsed;
    ThreadPool.QueueUserWorkItem(new WaitCallback(StatusThread));
    try
    {
      Console.Out.WriteLine("Opening connection. Timeout is {0} seconds.",
connection.ConnectionTimeout);
      // connection.Open() will never return on mono if
onExistingHost.dummyDomain cant be connected to
      connection.Open();
      elapsed = DateTime.Now - startTime;
      Console.Out.WriteLine("Connection opened in {0} seconds",
elapsed.TotalSeconds);
    }

    catch (Exception ex)
    {
      elapsed = DateTime.Now - startTime;
      Console.Out.WriteLine("Connection failed. Got {0} after {1} seconds",
ex.GetType().FullName, elapsed.TotalSeconds);
    }
    statusevent.Set();
  }

  static void StatusThread(object state)
  {
    // 60 s is just an example, we cant wait for infinity
    if (!statusevent.WaitOne(60 * 1000, false))
      Console.Out.WriteLine("connection.Open() has not returned after 60
seconds");
  }
}

-------------------

Run on .net:
Opening connection. Timeout is 10 seconds.
Connection failed. Got System.Data.SqlClient.SqlException after 12,4904312
seconds

Run on mono
Opening connection. Timeout is 10 seconds.
connection.Open() has not returned after 60 seconds

-------------------

I put in some ugly logging into mono and enabled disabled logging ("GONZ") in
the original mono code. Output is from SqlConnection.cs and
TdsConnectionPool.cs. Run on mono again:

Opening connection. Timeout is 10 seconds.
SqlConnection.Open()
  SqlConnection.Open() pooling is True
  SqlConnection.Open() Calling
TdsConnectionInfo(serverName=nonExistingHost.dummyDomain, port=1433,
packetSize=8000, ConnectionTimeout=10, minPoolSize=0, maxPoolSize=100
  SqlConnection.Open() Calling GetConnectionPool(connectionString=Data
Source=nonExistingHost.dummyDomain;Initial Catalog=myDataBase;User
Id=myUsername;Password=myPassword;Connection Timeout=10, info=...
  SqlConnection.Open() Calling GetConnection
GONZ: NEW
 CreateConnection tds42
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
connection.Open() has not returned after 60 seconds
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
 Mono.Data.Tds.Protocol.TdsTimeoutException
GONZ: NEW
 CreateConnection tds42
The application was terminated by a signal: SIGKILL

(app killed by me)

-------------------

The problem is in TdsConnectionPool.cs. Check my comments in the catch block.

lock (conns) {          
          if (conns.Count < info.PoolMaxSize) {
            try {
              Console.WriteLine ("GONZ: NEW");
              result = manager.CreateConnection (info);            
              conns.Add (result);
              return result; // no reset needed
            } catch {
              // Problem is that connection errors are caught here silently
              // Even if timeout (or any other error) occurs we loop over and
over again.
              // We will wait here forever for a new connection, regardless of
the timeout value
              // This is where I print the exception log messages above
            }
            continue;
          }
        }

-------------------

Proposed solution

Remove retry mechanism for new connections. If a new connection can not be
created, exception should propagate to user code immediatly.



Reproducible: Always

Steps to Reproduce:
Se above test code.
Actual Results:  
SqlConnection.Open() never returns.

Expected Results:  
SqlConnection.Open() should throw an exception after set timeout.

I'm setting the severity above normal. Without a patch for this, we have to
rewrite huge parts of our code to get it to run on mono. In general I think
that bugs that causes a thread to block for infinity always should be regarded
as severe.

-- 
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list