C# Driver 2.0.1 bug: timeout when authenticating with invalid credentials

395 views
Skip to first unread message

mikar

unread,
Sep 15, 2015, 7:49:39 AM9/15/15
to mongodb-user
Hello,

I'm posting this here since I don't have reporting permissions in the bug tracker.

Problem description: authenticating with invalid credentials always timeouts after 30 seconds with error: A timeout occurred after 30000ms selecting a server using CompositeServerSelector.

Steps to reproduce:
1. Start database server with command: "mongod --dbpath data --auth -v". Use empty database.
2. Create a console application in Visual Studio with the attached Program.cs. This connects to the admin database with username/password and executes a ping command.
3. Run the program.

Observed results: The ping command freezes for 30 seconds until it timeouts. Attempts to set any/all timeouts in MongoClientSettings make no difference. From the mongod log you can see that the client is repeatedly attempting to reconnect during the 30 second period.

Expected results: The client should attempt to login once. Once it detects that the credentials are invalid it should immediatelly cause an exception that indicates the correct error cause. It shouldn't be a TimeoutException but something more relevant to indicate that it was an credential problem.

Discussion: I didn't try to debug but by browsing the implementation I'm suspecting the problem is in ExclusiveConnectionPool.EnsureMinSizeAsync. That method has a loop which keeps opening new connections until enough connections are open (based on settings). But if there's an error when the connection is created it just keeps on looping and retrying. Meanwhile elsewhere we are waiting to get a connection from the pool but none are available so we're stuck until there's a timeout.

exception.txt
mongod.log
Program.cs

Craig Wilson

unread,
Sep 15, 2015, 9:20:15 AM9/15/15
to mongodb-user
Hi mikar,

The bug reporter is free and open. All you need is an account to use it. That being said, this is not a bug in the sense that this is behaving as designed. You certainly might wish it to behave differently and we have and are considering how to handle raising an more suitable exception. Much of the problem stems from the fact that we may be connected to more than one server, so there is a chance that you were successfully able to login to 2 servers but not another. What exception do we throw for that? And given a non-Primary read preference, this exception may be intermittent making it troubling and difficult to debug. 

For now, the [ServerSelectionTimeout](https://github.com/mongodb/mongo-csharp-driver/blob/master/src/MongoDB.Driver/MongoClientSettings.cs#L331) is the timeout that controls the, by default, 30 second period. Feel free to lower this setting to something better suited for your environment.

Craig

Mika Ryynänen

unread,
Sep 15, 2015, 3:26:28 PM9/15/15
to mongodb-user

Hello Craig,

I'm sure you are right that complex cases with multiple servers, clustering etc. can be problematic to handle. It's great that 2.1 driver will have ServerSelectionTimeout setting, but I think it's a design fault if the driver must rely on a timeout to detect invalid credentials. Just for comparison I made a quick test program with the Javascript driver. Here are the results compared:

C:\Temp>node auth
{ [MongoError: Authentication failed.]
  name: 'MongoError',
  message: 'Authentication failed.',
  ok: 0,
  code: 18,
  errmsg: 'Authentication failed.' }
auth: 40ms

C:\Temp>csharp
A timeout occured after 30000ms selecting a server using CompositeServerSelecto
Done in 30014 ms!

If I had the 2.1 version of the C# driver available I could use ServerSelectionTimeout, but still the Javascript driver handles this case better. Here are the test applications I used. They are mostly the same, main difference is that C# driver requires a command (ListCollectionsAsync) to perform the authentication and Javascript does it immediately when authenticate is called.


I'm sure there's some way to match performance from the C# driver with the Javascript version.. I was even thinking of using runCommand with saslStart manually but that sounds like too much work for such a simple thing. In the end ServerSelectionTimeout in 2.1 driver is probably good enough solution :)

Thanks! 
Mika

Craig Wilson

unread,
Sep 15, 2015, 3:56:10 PM9/15/15
to mongodb-user
Mike, with the 2.0.x  version of the driver, you can still set this setting. My apologies as I didn't realize this wasn't exposed in 2.0.x.  You can use the [ClusterConfigurator](https://github.com/mongodb/mongo-csharp-driver/blob/v2.0.1/src/MongoDB.Driver/MongoClientSettings.cs#L97) property to set this in the underlying cluster settings.

var settings = new MongoClientSettings
{
    ClusterConfigurator = cb => cb.ConfigureCluster(settings => settings.With(serverSelectionTimeout: TimeSpan.FromSeconds(5)));
};


Regarding performance with node, don't mistake that there is performance difference from this. The drivers simply behave differently. It's likely .NET has realized the failed authentication just as fast but is deciding to do something different with that knowledge according to the [server selection specification](https://github.com/mongodb/specifications/blob/master/source/server-selection/server-selection.rst#server-selection-errors). It has recently been changed, I just noticed, to incorporate an early exit if all the errors of each server are exactly the same. I've filed [CSHARP-1415](https://jira.mongodb.org/browse/CSHARP-1415) to track this getting completed. It will not be in 2.1 and I've scheduled it for 2.2, but since it's a non-API change, we may be able to backport to 2.1.1.

Also, I noticed you aren't comparing apples to apples here. In the .NET version, you've placed the credentials in the connection string, but not so in the node driver. I'm not saying it will make a difference though
Reply all
Reply to author
Forward
0 new messages