Skip to content

Commit 2fe7af3

Browse files
author
Robert Stam
committed
Fix CSHARP-454. RequestStart and RequestDone now hold the lock for less time to avoid deadlock.
1 parent 4cf29c9 commit 2fe7af3

File tree

1 file changed

+32
-18
lines changed

1 file changed

+32
-18
lines changed

Driver/Core/MongoServer.cs

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -993,23 +993,30 @@ public virtual void Reconnect()
993993
/// </summary>
994994
public virtual void RequestDone()
995995
{
996+
int threadId = Thread.CurrentThread.ManagedThreadId;
997+
MongoConnection connectionToRelease = null;
998+
996999
lock (_serverLock)
9971000
{
998-
int threadId = Thread.CurrentThread.ManagedThreadId;
9991001
Request request;
10001002
if (_requests.TryGetValue(threadId, out request))
10011003
{
10021004
if (--request.NestingLevel == 0)
10031005
{
10041006
_requests.Remove(threadId);
1005-
ReleaseConnection(request.Connection);
1007+
connectionToRelease = request.Connection;
10061008
}
10071009
}
10081010
else
10091011
{
10101012
throw new InvalidOperationException("Thread is not in a request (did you call RequestStart?).");
10111013
}
10121014
}
1015+
1016+
if (connectionToRelease != null)
1017+
{
1018+
connectionToRelease.ServerInstance.ReleaseConnection(connectionToRelease);
1019+
}
10131020
}
10141021

10151022
/// <summary>
@@ -1034,9 +1041,10 @@ public virtual IDisposable RequestStart(MongoDatabase initialDatabase)
10341041
/// <returns>A helper object that implements IDisposable and calls <see cref="RequestDone"/> from the Dispose method.</returns>
10351042
public virtual IDisposable RequestStart(MongoDatabase initialDatabase, bool slaveOk)
10361043
{
1044+
int threadId = Thread.CurrentThread.ManagedThreadId;
1045+
10371046
lock (_serverLock)
10381047
{
1039-
int threadId = Thread.CurrentThread.ManagedThreadId;
10401048
Request request;
10411049
if (_requests.TryGetValue(threadId, out request))
10421050
{
@@ -1045,15 +1053,18 @@ public virtual IDisposable RequestStart(MongoDatabase initialDatabase, bool slav
10451053
throw new InvalidOperationException("A nested call to RequestStart with slaveOk false is not allowed when the original call to RequestStart was made with slaveOk true.");
10461054
}
10471055
request.NestingLevel++;
1048-
}
1049-
else
1050-
{
1051-
var serverInstance = ChooseServerInstance(slaveOk);
1052-
var connection = serverInstance.AcquireConnection(initialDatabase);
1053-
request = new Request(connection, slaveOk);
1054-
_requests.Add(threadId, request);
1056+
return new RequestStartResult(this);
10551057
}
10561058

1059+
}
1060+
1061+
var serverInstance = ChooseServerInstance(slaveOk);
1062+
var connection = serverInstance.AcquireConnection(initialDatabase);
1063+
1064+
lock (_serverLock)
1065+
{
1066+
var request = new Request(connection, slaveOk);
1067+
_requests.Add(threadId, request);
10571068
return new RequestStartResult(this);
10581069
}
10591070
}
@@ -1068,9 +1079,10 @@ public virtual IDisposable RequestStart(MongoDatabase initialDatabase, bool slav
10681079
/// <returns>A helper object that implements IDisposable and calls <see cref="RequestDone"/> from the Dispose method.</returns>
10691080
public virtual IDisposable RequestStart(MongoDatabase initialDatabase, MongoServerInstance serverInstance)
10701081
{
1082+
int threadId = Thread.CurrentThread.ManagedThreadId;
1083+
10711084
lock (_serverLock)
10721085
{
1073-
int threadId = Thread.CurrentThread.ManagedThreadId;
10741086
Request request;
10751087
if (_requests.TryGetValue(threadId, out request))
10761088
{
@@ -1079,15 +1091,17 @@ public virtual IDisposable RequestStart(MongoDatabase initialDatabase, MongoServ
10791091
throw new InvalidOperationException("The server instance passed to a nested call to RequestStart does not match the server instance of the current Request.");
10801092
}
10811093
request.NestingLevel++;
1094+
return new RequestStartResult(this);
10821095
}
1083-
else
1084-
{
1085-
var connection = serverInstance.AcquireConnection(initialDatabase);
1086-
var slaveOk = serverInstance.IsSecondary;
1087-
request = new Request(connection, slaveOk);
1088-
_requests.Add(threadId, request);
1089-
}
1096+
}
10901097

1098+
var connection = serverInstance.AcquireConnection(initialDatabase);
1099+
var slaveOk = serverInstance.IsSecondary;
1100+
1101+
lock (_serverLock)
1102+
{
1103+
var request = new Request(connection, slaveOk);
1104+
_requests.Add(threadId, request);
10911105
return new RequestStartResult(this);
10921106
}
10931107
}

0 commit comments

Comments
 (0)