Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit ae029d5

Browse files
Set ConnectionState to Broken. Fixes #1599
When a socket/network error occurs, mark the connection as 'Broken', not 'Closed'. The user must explicitly Close the MySqlConnection (which will return it to the pool) before re-Opening it.
1 parent fd5aa32 commit ae029d5

File tree

5 files changed

+91
-9
lines changed

5 files changed

+91
-9
lines changed

‎src/MySqlConnector/Core/ServerSession.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2010,7 +2010,7 @@ internal void SetFailed(Exception exception)
20102010
lock (m_lock)
20112011
m_state = State.Failed;
20122012
if (OwningConnection is not null && OwningConnection.TryGetTarget(out var connection))
2013-
connection.SetState(ConnectionState.Closed);
2013+
connection.SetState(ConnectionState.Broken);
20142014
}
20152015

20162016
private void VerifyState(State state)

‎src/MySqlConnector/MySqlConnection.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -510,7 +510,7 @@ private async ValueTask<bool> PingAsync(IOBehavior ioBehavior, CancellationToken
510510
{
511511
}
512512

513-
SetState(ConnectionState.Closed);
513+
SetState(ConnectionState.Broken);
514514
return false;
515515
}
516516

‎tests/MySqlConnector.Tests/CancellationTests.cs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ public void Test(int step, int method)
329329
Assert.Null(ex.InnerException);
330330

331331
// connection is unusable
332-
Assert.Equal(ConnectionState.Closed, connection.State);
332+
Assert.Equal(ConnectionState.Broken, connection.State);
333333
}
334334
}
335335

@@ -351,7 +351,7 @@ public async Task Test(int step, int method)
351351
Assert.IsType<SocketException>(ex.InnerException);
352352

353353
// connection is unusable
354-
Assert.Equal(ConnectionState.Closed, connection.State);
354+
Assert.Equal(ConnectionState.Broken, connection.State);
355355
}
356356
}
357357

@@ -374,7 +374,7 @@ public void Execute(int step, int method)
374374
Assert.Null(ex.InnerException);
375375

376376
// connection is unusable
377-
Assert.Equal(ConnectionState.Closed, connection.State);
377+
Assert.Equal(ConnectionState.Broken, connection.State);
378378
}
379379

380380
[SkipCITheory]
@@ -394,7 +394,7 @@ public async Task ExecuteAsync(int step, int method)
394394
Assert.IsType<SocketException>(ex.InnerException);
395395

396396
// connection is unusable
397-
Assert.Equal(ConnectionState.Closed, connection.State);
397+
Assert.Equal(ConnectionState.Broken, connection.State);
398398
}
399399
}
400400

‎tests/MySqlConnector.Tests/ConnectionTests.cs‎

Lines changed: 69 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ public void Ping()
166166
}
167167

168168
[Fact]
169-
public void PingWhenClosed()
169+
public void PingWhenReset()
170170
{
171171
using var connection = new MySqlConnection(m_csb.ConnectionString);
172172
connection.Open();
173173
Assert.Equal(ConnectionState.Open, connection.State);
174-
m_server.Stop();
174+
m_server.Reset();
175175
Assert.False(connection.Ping());
176-
Assert.Equal(ConnectionState.Closed, connection.State);
176+
Assert.Equal(ConnectionState.Broken, connection.State);
177177
}
178178

179179
[Fact]
@@ -277,6 +277,72 @@ public void ReplaceActiveReader()
277277
connection.Close();
278278
}
279279

280+
[Fact]
281+
public async Task ResetServerConnectionWhileOpen()
282+
{
283+
var csb = new MySqlConnectionStringBuilder(m_csb.ConnectionString)
284+
{
285+
MaximumPoolSize = 5,
286+
ConnectionTimeout = 5,
287+
};
288+
289+
List<Task> tasks = [];
290+
using var barrier = new Barrier((int) csb.MaximumPoolSize);
291+
for (var i = 0; i < csb.MaximumPoolSize - 1; i++)
292+
{
293+
var threadId = i;
294+
tasks.Add(Task.Run(async () =>
295+
{
296+
using var connection = new MySqlConnection(csb.ConnectionString);
297+
await connection.OpenAsync().ConfigureAwait(false);
298+
299+
barrier.SignalAndWait();
300+
//// wait for reset
301+
barrier.SignalAndWait();
302+
303+
switch (threadId % 3)
304+
{
305+
case 0:
306+
{
307+
using (var command = connection.CreateCommand())
308+
{
309+
command.CommandText = "SELECT 1;";
310+
var exception = Assert.Throws<MySqlException>(() => command.ExecuteScalar());
311+
Assert.Equal("Failed to read the result set.", exception.Message);
312+
}
313+
break;
314+
}
315+
case 1:
316+
{
317+
// NOTE: duplicate of PingWhenReset, but included here for completeness
318+
var ping = await connection.PingAsync().ConfigureAwait(false);
319+
Assert.False(ping);
320+
break;
321+
}
322+
case 2:
323+
{
324+
await Assert.ThrowsAnyAsync<Exception>(async () => await connection.ResetConnectionAsync().ConfigureAwait(false));
325+
break;
326+
}
327+
}
328+
329+
Assert.Equal(ConnectionState.Broken, connection.State);
330+
331+
await connection.CloseAsync().ConfigureAwait(false);
332+
Assert.Equal(ConnectionState.Closed, connection.State);
333+
334+
await connection.OpenAsync().ConfigureAwait(false);
335+
Assert.Equal(ConnectionState.Open, connection.State);
336+
}));
337+
}
338+
339+
barrier.SignalAndWait();
340+
m_server.Reset();
341+
barrier.SignalAndWait();
342+
343+
await Task.WhenAll(tasks);
344+
}
345+
280346
private static async Task WaitForConditionAsync<T>(T expected, Func<T> getValue)
281347
{
282348
var sw = Stopwatch.StartNew();

‎tests/MySqlConnector.Tests/FakeMySqlServer.cs‎

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ public void Start()
2121
m_tasks.Add(AcceptConnectionsAsync());
2222
}
2323

24+
public void Reset()
25+
{
26+
m_cts.Cancel();
27+
try
28+
{
29+
Task.WaitAll(m_tasks.Skip(1).ToArray());
30+
}
31+
catch (AggregateException)
32+
{
33+
}
34+
m_connections.Clear();
35+
m_tasks.Clear();
36+
m_cts.Dispose();
37+
m_cts = new();
38+
}
39+
2440
public void Stop()
2541
{
2642
if (m_cts is not null)

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /