Skip to content

Commit 2842f27

Browse files
authored
1552 mqttnetservermqttclientsessionsmanager subscribersessions is not proper removed on special case (#1562)
1 parent 7ef137e commit 2842f27

File tree

10 files changed

+349
-145
lines changed

10 files changed

+349
-145
lines changed

.github/workflows/ReleaseNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
* [Core] Fixed several dead locks by implementing a new async signal (#1552)
12
* [Server] Fixed duplicated invocation of the event _ClientAcknowledgedPublishPacketAsync_ for QoS level 2 (#1550)
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Diagnostics;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
using MQTTnet.Internal;
11+
12+
namespace MQTTnet.Tests.Internal
13+
{
14+
[TestClass]
15+
public sealed class AsyncSignal_Tests
16+
{
17+
[TestMethod]
18+
[ExpectedException(typeof(TaskCanceledException))]
19+
public async Task Cancel_If_No_Signal()
20+
{
21+
var asyncSignal = new AsyncSignal();
22+
23+
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(2)))
24+
{
25+
await asyncSignal.WaitAsync(timeout.Token);
26+
27+
Assert.Fail("There is no signal. So we must fail here!");
28+
}
29+
}
30+
31+
[TestMethod]
32+
[ExpectedException(typeof(ObjectDisposedException))]
33+
public async Task Dispose_Properly()
34+
{
35+
var asyncSignal = new AsyncSignal();
36+
37+
// The timeout will not be reached but another task will kill the async signal.
38+
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(999)))
39+
{
40+
_ = Task.Run(
41+
async () =>
42+
{
43+
await Task.Delay(2000, CancellationToken.None);
44+
asyncSignal.Dispose();
45+
},
46+
CancellationToken.None);
47+
48+
await asyncSignal.WaitAsync(timeout.Token);
49+
50+
Assert.Fail("There is no signal. So we must fail here!");
51+
}
52+
}
53+
54+
[TestMethod]
55+
public async Task Loop_Signal()
56+
{
57+
var asyncSignal = new AsyncSignal();
58+
59+
for (var i = 0; i < 10; i++)
60+
{
61+
asyncSignal.Set();
62+
63+
// WaitAsync should return directly because the signal is available.
64+
await asyncSignal.WaitAsync();
65+
}
66+
}
67+
68+
[TestMethod]
69+
public async Task Signal()
70+
{
71+
var asyncSignal = new AsyncSignal();
72+
73+
// The timeout will not be reached but another task will kill the async signal.
74+
using (var timeout = new CancellationTokenSource(TimeSpan.FromSeconds(3)))
75+
{
76+
var stopwatch = Stopwatch.StartNew();
77+
78+
_ = Task.Run(
79+
async () =>
80+
{
81+
await Task.Delay(1000, CancellationToken.None);
82+
asyncSignal.Set();
83+
},
84+
CancellationToken.None);
85+
86+
await asyncSignal.WaitAsync(timeout.Token);
87+
88+
stopwatch.Stop();
89+
90+
Assert.IsTrue(stopwatch.ElapsedMilliseconds > 900);
91+
}
92+
}
93+
94+
[TestMethod]
95+
[ExpectedException(typeof(InvalidOperationException))]
96+
public async Task Fail_For_Two_Waiters()
97+
{
98+
var asyncSignal = new AsyncSignal();
99+
100+
// This thread will wait properly because it is the first waiter.
101+
_ = Task.Run(
102+
async () =>
103+
{
104+
await asyncSignal.WaitAsync();
105+
},
106+
CancellationToken.None);
107+
108+
await Task.Delay(1000);
109+
110+
// Now the current thread must fail because there is already a waiter.
111+
await asyncSignal.WaitAsync();
112+
}
113+
}
114+
}

Source/MQTTnet.Tests/Internal/MqttPacketBus_Tests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace MQTTnet.Tests.Internal
1515
public sealed class MqttPacketBus_Tests
1616
{
1717
[TestMethod]
18-
[ExpectedException(typeof(OperationCanceledException))]
18+
[ExpectedException(typeof(TaskCanceledException))]
1919
public async Task Wait_With_Empty_Bus()
2020
{
2121
var bus = new MqttPacketBus();

Source/MQTTnet.Tests/Server/Load_Tests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ await client.PublishAsync(message)
5555
});
5656
}
5757

58-
SpinWait.SpinUntil(() => receivedMessages == 100000, TimeSpan.FromSeconds(60));
58+
SpinWait.SpinUntil(() => receivedMessages == 100000, TimeSpan.FromSeconds(90));
5959

6060
Assert.AreEqual(100000, receivedMessages);
6161
}

0 commit comments

Comments
 (0)