dotnet / dotnet/MQTTnet

About the memory error problem of InjectApplicationMessage of MqttServer in client.WithCleanSession(false)

Open
#2,113 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
C#
Stars
5.1k
Forks
1.2k
PR merge metrics
No merged PRs in 30d

Description

### Describe the bug
When I was doing performance optimization extension for MqttServer's InjectApplicationMessage , I used `ArrayPool` memory and unexpectedly found that the test [QoS_Tests.Preserve_Message_Order_For_Queued_Messages](https://github.com/dotnet/MQTTnet/blob/master/Source/MQTTnet.Tests/Server/QoS_Tests.cs#L115) failed because I cleared and recycled poolPayload after `await MqttServer.InjectApplicationMessage( poolPayload)` . I think there is no problem with my operation timing, and this behavior should be allowed.

If I use the byte[] poolPayload that I manually new, this test is successful. The reason is that the caller provides a payload in an independent space for InjectApplicationMessage, and this payload will only be used by MqttServer in the future until it is recycled by GC.

### Which component is your bug related to?

- Server

### To Reproduce
Modify the InjectApplicationMessage code of MqttServerExtensions and run the test Preserve_Message_Order_For_Queued_Messages.

```c#
public static async Task InjectApplicationMessage(
this MqttServer server,
string topic,
string payload = null,
MqttQualityOfServiceLevel qualityOfServiceLevel = MqttQualityOfServiceLevel.AtMostOnce,
bool retain = false)
{
ArgumentNullException.ThrowIfNull(server);
ArgumentNullException.ThrowIfNull(topic);

var payloadBuffer = Encoding.UTF8.GetBytes(payload ?? string.Empty);

var message = new MqttApplicationMessageBuilder()
.WithTopic(topic)
.WithPayload(payloadBuffer)
.WithQualityOfServiceLevel(qualityOfServiceLevel)
.WithRetainFlag(retain)
.Build();

await server.InjectApplicationMessage(new InjectedMqttApplicationMessage(message));

// clear the buffer
payloadBuffer.AsSpan().Clear();
}
```
### Expected behavior
After await InjectApplicationMessage(), the memory reference to the payload must be released.

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.