Azure-Samples / Azure-Samples/iot-middleware-freertos-samples
Possible race condition with C2D messaging
- Dominant language
- CMake
- Stars
- 88
- Forks
- 54
- PR merge metrics
- No merged PRs in 30d
Description
I've found that the Cloud-to-Device (C2D) messages sent while the device is offline are lost when the device reconnects, despite being properly queued by Azure IoT Hub.
## Environment
- **Platform**: ESP32 with FreeRTOS
- **Connection type**: MQTT with persistent session (cleanSession = false)
## Expected Behaviour
C2D messages sent while device is offline should be delivered when the device reconnects and calls `AzureIoTHubClient_SubscribeCloudToDeviceMessage()`.
## Actual Behavior
Queued C2D messages arrive immediately after MQTT CONNACK but are dropped with "No receive context found" because subscription handlers are not yet registered.
## Reproduction Steps
1. Send C2D messages while device is offline
2. Device reconnects with `cleanSession = false`
3. Device calls `AzureIoTHubClient_Connect()` followed immediately by `AzureIoTHubClient_SubscribeCloudToDeviceMessage()`
4. Observe logs showing messages being dropped
## Logs
I (6780) MQTT: Packet received. ReceivedBytes=2.
I (6780) MQTT: CONNACK session present bit set.
I (6780) MQTT: Connection accepted.
I (6780) MQTT: Received MQTT CONNACK successfully from broker.
I (6780) MQTT: MQTT connection established with the broker.
I (6780) AZ IOT: An MQTT connection is established with OEDeviceHub.azure-devices.net
I (6790) MQTT: Packet received. ReceivedBytes=193.
I (6790) MQTT: De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
I (6790) MQTT: State record updated. New state=MQTTPubAckSend.
I (6790) AZ IOT: No receive context found for incoming publish on topic: devices/CCBA97F5E66C/messages/devicebound/%24.to=%2Fdevices%2FCCBA97F5E66C%2Fmessages%2FdeviceBound&%24.ct=application%2Fjson&%24.ce=utf-8&messageId=8eb8e2f9-817a-4c32-abfd-3a93f32145a3
if C2D messages are sent whilst the device is already connected, and subscribed to C2D messages, then the messages are handled correctly:
I (13040) MQTT: Packet received. ReceivedBytes=193.
I (13040) MQTT: De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
I (13040) MQTT: State record updated. New state=MQTTPubAckSend.
I (13040) AZ IOT: devices/CCBA97F5E66C/messages/devicebound/%24.to=%2Fdevices%2FCCBA97F5E66C%2Fmessages%2FdeviceBound&%24.ct=application%2Fjson&%24.ce=utf-8&messageId=a8855ef6-b6c4-4fe9-9f36-040070114917
I (13040) AZ IOT: === C2D MESSAGE RECEIVED - Length: 4 ===
I (13040) AZ IOT: C2D Message payload: test
I (13040) AZ IOT: Received test message
I (13060) AZ IOT: End of main azure loop
Has anyone experienced this? I am under the impression that C2D messages are designed to be queued, as opposed to direct method messaging.
I have TTL at 1 hour, and the testing of turning the device on/off was well within that time frame.
Any help would be much appreciated thank you.
Contributor guide
Assessment
This issue has not been assessed yet.