eclipse/paho.mqtt.c

V1.3.13: Memory leak when call MQTTAsync_sendMessage with QOS0

Opened this issue · 5 comments

Description:
Memory leak when call MQTTAsync_sendMessage with QOS0

Reproduce:

  1. Connect the mqtt broker.
  2. Unplug the ethernet wire. (I didn't check this state in my system) --> Must do this.
  3. No connection lost callback happen now.
  4. Call MQTTAsync_sendMessage with QOS0 to send 16K data for example
    4.1 MQTTAsync_sendMessage 16K data, then return send OK, but onSendSuccess callback didn't be called.
    Usually the payload will be free automatically after onSendSuccess be called.
    But I didn't get this be called.
  5. After 10s later, call MQTTAsync_disconnect & MQTTAsync_destroy.
  6. Then the memleak happened.

I think the leak was cause by MQTTASYNC_OPERATION_INCOMPLETE.

Log:
onSendFailure 128: Message send failed token 0 error code -11, --> MQTTASYNC_OPERATION_INCOMPLETE
onSendFailure 133: Failed to start disconnect, return code -3, Disconnected
onSendFailure 128: Message send failed token 0 error code -11,
onSendFailure 133: Failed to start disconnect, return code -3, Disconnected
trace_callback 214: Trace : 5, 20231205 162437.367 Some memory not freed at shutdown, possible memory leak
trace_callback 214: Trace : 5, 20231205 162437.367 Heap scan start, total 1584304 bytes
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 48, line 1108, file ../xxx/lib/paho.mqtt.c/MQTTProtocolClient.c, ptr 0x28b468
trace_callback 214: Trace : 5, 20231205 162437.367 Content 111/O
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 48, line 1108, file ../xxx/lib/paho.mqtt.c/MQTTProtocolClient.c, ptr 0x298740
trace_callback 214: Trace : 5, 20231205 162437.367 Content 111/O
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 72624, line 1277, file ../xxx/lib/paho.mqtt.c/MQTTAsync.c, ptr 0x3fc6b0
trace_callback 214: Trace : 5, 20231205 162437.367 Content {"Md5Code"
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 90336, line 1277, file ../xxx/lib/paho.mqtt.c/MQTTAsync.c, ptr 0x4390a8
trace_callback 214: Trace : 5, 20231205 162437.367 Content {"Id":0,"P
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 16, line 92, file ../xxx/lib/paho.mqtt.c/LinkedList.c, ptr 0xb4600598
trace_callback 214: Trace : 5, 20231205 162437.367 Content
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 32, line 264, file ../xxx/lib/paho.mqtt.c/MQTTProtocolClient.c, ptr 0xb4600a68
trace_callback 214: Trace : 5, 20231205 162437.367 Content p?(
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 16, line 92, file ../xxx/lib/paho.mqtt.c/LinkedList.c, ptr 0xb4600e30
trace_callback 214: Trace : 5, 20231205 162437.367 Content
trace_callback 214: Trace : 5, 20231205 162437.367 Heap element size 16, line 116, file ../xxx/lib/paho.mqtt.c/MQTTProtocolClient.c, ptr 0xb4601678
trace_callback 214: Trace : 5, 20231205 162437.367 Content

In MQTTAsync_processCommand:
if (command->command.details.pub.qos == 0)
{
if (rc == TCPSOCKET_COMPLETE)
{
if (command->command.onSuccess)
{
...
}
...
}
else
{
if (rc != SOCKET_ERROR)
{
///// the payload was set to NULL here, and may be cause we didn't free the payload when we call MQTTAsync_destroy.
command->command.details.pub.payload = NULL; /* this will be freed by the protocol code /
command->command.details.pub.destinationName = NULL; /
this will be freed by the protocol code */
}
command->client->pending_write = &command->command;
}
}

Anyone who can help me on this issue?
Thanks!

Did you set the onFailure callback as well as onSuccess?

How long is your keepalive interval? When you pull the network cable out TCP stacks can respond in different ways, and take some time before the connection is recognized as broken. A shorter keep alive interval will allow this to happen more quickly - the connectionLost callback indicating it.

You haven't said what OS you are using.

Thanks for your reply!
I have set the onFailure callback already.
I have set the keepalive to 30s.
I am using Linux.

My application scenario is as follows: client -> broker -> server.
The client sends data to the server with QoS 0.
If the server receives it, it will reply with an acknowledgment using our own private protocol.
If the client receives the acknowledgment within 10 seconds, it is considered successful and I will release the memory.
Otherwise, it is considered a failed send, and I will resend the data.
There will be 3 retransmissions.
If it still fails after 3 retransmissions, I will call MQTTAsync_destroy. At this point, a memory leak occurs.

I did the above test with network cable disconnected.
Is there any method to force free any mqtt comand at any time after I publish the message?

Thanks!

What is the status of this issue?