RPC_Response, Dangling Reference
Hello all, "process_rpc_message" is calling the callback function "processTemperatureChange". The callback function must return RPC_Response object. Now lets consider the example [0010-esp8266_esp32_rpc]. İn 0010-esp8266_esp32_rpc.ino file, function loop() we are registering the callback functions:
const std::array<RPC_Callback, 2U> callbacks = {
RPC_Callback{ RPC_TEMPERATURE_METHOD, processTemperatureChange },
RPC_Callback{ RPC_SWITCH_METHOD, processSwitchChange }
};
// Perform a subscription. All consequent data processing will happen in
// processTemperatureChange() and processSwitchChange() functions,
// as denoted by callbacks array.
if (!tb.RPC_Subscribe(callbacks.cbegin(), callbacks.cend())) {
#if THINGSBOARD_ENABLE_PROGMEM
Serial.println(F("Failed to subscribe for RPC"));
#else
Serial.println("Failed to subscribe for RPC");
#endif
return;
}
and one of the callback function is :
RPC_Response processTemperatureChange(const RPC_Data &data) {
#if THINGSBOARD_ENABLE_PROGMEM
Serial.println(F("Received the set temperature RPC method"));
#else
Serial.println("Received the set temperature RPC method");
#endif
// Process data
const float example_temperature = data[RPC_TEMPERATURE_KEY];
#if THINGSBOARD_ENABLE_PROGMEM
Serial.print(F("Example temperature: "));
#else
Serial.print("Example temperature: ");
#endif
Serial.println(example_temperature);
// Just an response example
StaticJsonDocument<JSON_OBJECT_SIZE(1)> doc;
doc[RPC_RESPONSE_KEY] = 42;
return RPC_Response(doc);
}
In the callback function 'processTemperatureChange', The 'StaticJsonDocument' object is created locally and passed as an argument to RPC_Response constructor. The called RPC_Response constructor is the one with the parameter JsonVariant.
explicit RPC_Response(JsonVariant variant);
Now the local 'StaticJsonDocument' object is impilicitly converted to 'JsonVariant', which means 'JsonVariant' is referencing the local 'StaticJsonDocument' object. The 'process_rpc_message' gets the callback function's("processTemperatureChange") return value as a response.
RPC_Response response;
...
response = rpc.Call_Callback<Logger>(param);
As soon as callback function is finished, local object 'StaticJsonDocument' lifetime is over and the returned value RPC_Response is now referencing a released source 'StaticJsonDocument'. Undefined behaviour. The solution can be: RPC_Response class can store the JsonDocument so that we can move the locally created 'StaticJsonDocument' object and then use it when sending the response to the server. Thanks in advance.
Already known thanks to issue #167, is fixed in the aforementioned pull request. As soon as it has been merged the issue will be resolved.
Thank you for the quick response.