Fix MQTT packet ACK (#21416)
invalidate sending_frag when marking messages for garbage collection
Stelios Fragkakis committed
Dec 8, 2025 at 22:23 UTC
59119aae4b0983c4acf3f212da8c1f2104f5474b
1 file changed
+23
src/aclk/mqtt_websockets/mqtt_ng.c
+23
@@ -1177,6 +1177,20 @@ static void mark_message_for_gc(struct buffer_fragment *frag)
1177
}
1178
}
1179
1180
+// Check if sending_frag points to any fragment in the message starting at msg_head
1181
+static bool sending_frag_in_message(struct transaction_buffer *buf, struct buffer_fragment *msg_head)
1182
+{
1183
+ struct buffer_fragment *frag = msg_head;
1184
+ while (frag) {
1185
+ if (buf->sending_frag == frag)
1186
+ return true;
1187
+ if (frag->flags & BUFFER_FRAG_MQTT_PACKET_TAIL)
1188
+ return false;
1189
+ frag = frag->next;
1190
+ }
1191
+ return false;
1192
+}
1193
+
1194
static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1195
{
1196
size_t reclaimable = 0;
@@ -1196,6 +1210,12 @@ static int mark_packet_acked(struct mqtt_ng_client *client, uint16_t packet_id)
1210
usec_t latency = now_monotonic_usec() - frag->sent_monotonic_ut;
1211
pulse_aclk_sent_message_acked(latency, frag->len);
1212
__atomic_store_n(&publish_latency, latency, __ATOMIC_RELEASE);
1213
+
1214
+ // Invalidate sending_frag if it points to any fragment in this message
1215
+ // since mark_message_for_gc will free the data
1216
+ if (sending_frag_in_message(&client->main_buffer, frag))
1217
+ client->main_buffer.sending_frag = NULL;
1218
+
1219
mark_message_for_gc(frag);
1220
1221
size_t used = BUFFER_BYTES_USED(&client->main_buffer.hdr_buffer);
@@ -2096,6 +2116,9 @@ int handle_incoming_traffic(struct mqtt_ng_client *client)
2116
worker_is_busy(WORKER_ACLK_CPT_CONNACK);
2117
2118
LOCK_HDR_BUFFER(&client->main_buffer);
2119
+ // Invalidate sending_frag if it points to any fragment in the CONNECT message
2120
+ if (sending_frag_in_message(&client->main_buffer, client->connect_msg))
2121
+ client->main_buffer.sending_frag = NULL;
2122
mark_message_for_gc(client->connect_msg);
2123
UNLOCK_HDR_BUFFER(&client->main_buffer);
2124