mirror of
https://github.com/dotnet/MQTTnet.git
synced 2026-10-18 02:13:00 +08:00
Fix freezes in _AsyncLock_ (#1549)
This commit is contained in:
@@ -10,6 +10,7 @@ using System.Text;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
@@ -88,7 +89,7 @@ namespace MQTTnet.Server
|
||||
/// </summary>
|
||||
public uint MaximumPacketSize => _connectPacket.MaximumPacketSize;
|
||||
|
||||
public string Password => Encoding.UTF8.GetString(RawPassword ?? PlatformAbstractionLayer.EmptyByteArray);
|
||||
public string Password => Encoding.UTF8.GetString(RawPassword ?? EmptyBuffer.Array);
|
||||
|
||||
public MqttProtocolVersion ProtocolVersion => ChannelAdapter.PacketFormatterAdapter.ProtocolVersion;
|
||||
|
||||
|
||||
@@ -181,7 +181,7 @@ namespace MQTTnet.Server
|
||||
return _eventContainer.ClientAcknowledgedPublishPacketEvent.TryInvokeAsync(eventArgs, _logger);
|
||||
}
|
||||
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
return CompletedTask.Instance;
|
||||
}
|
||||
|
||||
Task HandleIncomingPubAckPacket(MqttPubAckPacket pubAckPacket)
|
||||
@@ -193,7 +193,7 @@ namespace MQTTnet.Server
|
||||
return ClientAcknowledgedPublishPacket(acknowledgedPublishPacket, pubAckPacket);
|
||||
}
|
||||
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
return CompletedTask.Instance;
|
||||
}
|
||||
|
||||
Task HandleIncomingPubCompPacket(MqttPubCompPacket pubCompPacket)
|
||||
@@ -205,7 +205,7 @@ namespace MQTTnet.Server
|
||||
return ClientAcknowledgedPublishPacket(acknowledgedPublishPacket, pubCompPacket);
|
||||
}
|
||||
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
return CompletedTask.Instance;
|
||||
}
|
||||
|
||||
async Task HandleIncomingPublishPacket(MqttPublishPacket publishPacket, CancellationToken cancellationToken)
|
||||
|
||||
@@ -306,6 +306,9 @@ namespace MQTTnet.Server
|
||||
|
||||
await client.RunAsync().ConfigureAwait(false);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
}
|
||||
@@ -479,7 +482,7 @@ namespace MQTTnet.Server
|
||||
sessionShouldPersist = !connectPacket.CleanSession;
|
||||
}
|
||||
|
||||
using (await _createConnectionSyncRoot.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||
using (await _createConnectionSyncRoot.EnterAsync().ConfigureAwait(false))
|
||||
{
|
||||
MqttSession session;
|
||||
lock (_sessionsManagementLock)
|
||||
@@ -537,6 +540,7 @@ namespace MQTTnet.Server
|
||||
MqttClientDisconnectType.Takeover,
|
||||
existingClient.Endpoint,
|
||||
existingClient.Session.Items);
|
||||
|
||||
await _eventContainer.ClientDisconnectedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
@@ -85,7 +83,7 @@ namespace MQTTnet.Server
|
||||
}
|
||||
else
|
||||
{
|
||||
if (existingMessage.QualityOfServiceLevel != applicationMessage.QualityOfServiceLevel || !existingMessage.Payload.SequenceEqual(applicationMessage.Payload ?? PlatformAbstractionLayer.EmptyByteArray))
|
||||
if (existingMessage.QualityOfServiceLevel != applicationMessage.QualityOfServiceLevel || !existingMessage.Payload.SequenceEqual(applicationMessage.Payload ?? EmptyBuffer.Array))
|
||||
{
|
||||
_messages[applicationMessage.Topic] = applicationMessage;
|
||||
saveIsRequired = true;
|
||||
@@ -103,7 +101,7 @@ namespace MQTTnet.Server
|
||||
|
||||
if (saveIsRequired)
|
||||
{
|
||||
using (await _storageAccessLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||
using (await _storageAccessLock.EnterAsync().ConfigureAwait(false))
|
||||
{
|
||||
var eventArgs = new RetainedMessageChangedEventArgs(clientId, applicationMessage, messagesForSave);
|
||||
await _eventContainer.RetainedMessageChangedEvent.InvokeAsync(eventArgs).ConfigureAwait(false);
|
||||
@@ -132,7 +130,7 @@ namespace MQTTnet.Server
|
||||
_messages.Clear();
|
||||
}
|
||||
|
||||
using (await _storageAccessLock.WaitAsync(CancellationToken.None).ConfigureAwait(false))
|
||||
using (await _storageAccessLock.EnterAsync().ConfigureAwait(false))
|
||||
{
|
||||
await _eventContainer.RetainedMessagesClearedEvent.InvokeAsync(EventArgs.Empty).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Protocol;
|
||||
|
||||
@@ -14,16 +13,20 @@ namespace MQTTnet.Server
|
||||
{
|
||||
public sealed class MqttServerKeepAliveMonitor
|
||||
{
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
readonly MqttServerOptions _options;
|
||||
readonly MqttClientSessionsManager _sessionsManager;
|
||||
readonly MqttNetSourceLogger _logger;
|
||||
|
||||
public MqttServerKeepAliveMonitor(MqttServerOptions options, MqttClientSessionsManager sessionsManager, IMqttNetLogger logger)
|
||||
{
|
||||
_options = options ?? throw new ArgumentNullException(nameof(options));
|
||||
_sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager));
|
||||
|
||||
if (logger == null) throw new ArgumentNullException(nameof(logger));
|
||||
|
||||
if (logger == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(logger));
|
||||
}
|
||||
|
||||
_logger = logger.WithSource(nameof(MqttServerKeepAliveMonitor));
|
||||
}
|
||||
|
||||
@@ -45,7 +48,7 @@ namespace MQTTnet.Server
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
TryProcessClients();
|
||||
PlatformAbstractionLayer.Sleep(_options.KeepAliveMonitorInterval);
|
||||
Sleep(_options.KeepAliveMonitorInterval);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
@@ -61,13 +64,22 @@ namespace MQTTnet.Server
|
||||
}
|
||||
}
|
||||
|
||||
void TryProcessClients()
|
||||
static void Sleep(TimeSpan timeout)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
foreach (var client in _sessionsManager.GetClients())
|
||||
#if !NETSTANDARD1_3 && !WINDOWS_UWP
|
||||
try
|
||||
{
|
||||
TryProcessClient(client, now);
|
||||
Thread.Sleep(timeout);
|
||||
}
|
||||
catch (ThreadAbortException)
|
||||
{
|
||||
// The ThreadAbortException is not actively catched in this project.
|
||||
// So we use a one which is similar and will be catched properly.
|
||||
throw new OperationCanceledException();
|
||||
}
|
||||
#else
|
||||
Task.Delay(timeout).Wait();
|
||||
#endif
|
||||
}
|
||||
|
||||
void TryProcessClient(MqttClient connection, DateTime now)
|
||||
@@ -119,5 +131,14 @@ namespace MQTTnet.Server
|
||||
_logger.Error(exception, "Client {0}: Unhandled exception while checking keep alive timeouts.", connection.Id);
|
||||
}
|
||||
}
|
||||
|
||||
void TryProcessClients()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
foreach (var client in _sessionsManager.GetClients())
|
||||
{
|
||||
TryProcessClient(client, now);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Adapter;
|
||||
using MQTTnet.Diagnostics;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
using MQTTnet.Packets;
|
||||
using MQTTnet.Protocol;
|
||||
@@ -172,7 +171,7 @@ namespace MQTTnet.Server
|
||||
{
|
||||
ThrowIfNotStarted();
|
||||
|
||||
return _retainedMessagesManager?.ClearMessages() ?? PlatformAbstractionLayer.CompletedTask;
|
||||
return _retainedMessagesManager?.ClearMessages() ?? CompletedTask.Instance;
|
||||
}
|
||||
|
||||
public Task DisconnectClientAsync(string id, MqttDisconnectReasonCode reasonCode)
|
||||
|
||||
@@ -6,7 +6,6 @@ using System;
|
||||
using System.Collections;
|
||||
using System.Threading.Tasks;
|
||||
using MQTTnet.Formatter;
|
||||
using MQTTnet.Implementations;
|
||||
using MQTTnet.Internal;
|
||||
|
||||
namespace MQTTnet.Server
|
||||
@@ -34,8 +33,8 @@ namespace MQTTnet.Server
|
||||
|
||||
var publishPacketFactory = new MqttPublishPacketFactory();
|
||||
_session.EnqueueDataPacket(new MqttPacketBusItem(publishPacketFactory.Create(applicationMessage)));
|
||||
|
||||
return PlatformAbstractionLayer.CompletedTask;
|
||||
|
||||
return CompletedTask.Instance;
|
||||
}
|
||||
|
||||
public Task DeliverApplicationMessageAsync(MqttApplicationMessage applicationMessage)
|
||||
|
||||
Reference in New Issue
Block a user