Azure-Samples / Azure-Samples/iot-middleware-freertos-samples

Possible race condition with C2D messaging

Open
#397 0 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.