mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2026-06-13 19:36:26 +03:00
fix: run message/sendmail shunting-yard synchronously to avoid main-loop deadlock
command_message() and command_sendmail() handed their value to WebSchedulerService via raw_value and busy-waited up to 2s for the scheduler loop (running in a separate task) to compute it. After the scheduler was moved to run synchronously in the main loop, any caller running in the main loop (MQTT-triggered commands, scheduler-triggered commands) deadlocks: the loop that would compute raw_value cannot run while the caller is blocking inside it. The 2s wait then times out and system/message fails entirely (sendmail sends the un-computed body). Compute the value directly with compute() instead, which restores correct behaviour for all callers. Co-authored-by: Proddy <proddy@users.noreply.github.com>
This commit is contained in:
@@ -32,6 +32,7 @@
|
||||
#include <map>
|
||||
|
||||
#include "firmwareVersion.h"
|
||||
#include "shuntingYard.h" // for compute() used by the message and sendmail commands
|
||||
|
||||
#if defined(EMSESP_TEST)
|
||||
#include "../test/test.h"
|
||||
@@ -194,15 +195,11 @@ bool System::command_sendmail(const char * value, const int8_t id) {
|
||||
// msg.headers.addCustom("Importance", PRIORITY);
|
||||
// msg.headers.addCustom("X-MSMail-Priority", PRIORITY);
|
||||
// msg.headers.addCustom("X-Priority", PRIORITY_NUM);
|
||||
EMSESP::webSchedulerService.computed_value.clear();
|
||||
EMSESP::webSchedulerService.raw_value = body.c_str();
|
||||
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) {
|
||||
delay(1);
|
||||
}
|
||||
if (!EMSESP::webSchedulerService.computed_value.empty()) {
|
||||
body = EMSESP::webSchedulerService.computed_value.c_str();
|
||||
EMSESP::webSchedulerService.computed_value.clear();
|
||||
EMSESP::webSchedulerService.computed_value.shrink_to_fit(); // free allocated memory
|
||||
// run the body through the Shunting Yard calculator (entity substitution, expressions, optional {url} fetch)
|
||||
// keep the original body if the calculator returns nothing
|
||||
std::string computed_body = compute(body.c_str());
|
||||
if (!computed_body.empty()) {
|
||||
body = computed_body.c_str();
|
||||
}
|
||||
msg.text.body(body);
|
||||
|
||||
@@ -344,22 +341,16 @@ bool System::command_message(const char * value, const int8_t id, JsonObject out
|
||||
return false; // must have a string value
|
||||
}
|
||||
|
||||
EMSESP::webSchedulerService.computed_value.clear();
|
||||
EMSESP::webSchedulerService.raw_value = value;
|
||||
for (uint16_t wait = 0; wait < 2000 && !EMSESP::webSchedulerService.raw_value.empty(); wait++) {
|
||||
delay(1);
|
||||
}
|
||||
|
||||
if (EMSESP::webSchedulerService.computed_value.empty()) {
|
||||
// process the message via the Shunting Yard calculator (entity substitution, expressions, optional {url} fetch)
|
||||
std::string computed_value = compute(value);
|
||||
if (computed_value.empty()) {
|
||||
LOG_WARNING("Message result is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_INFO("Message: %s", EMSESP::webSchedulerService.computed_value.c_str()); // send to log
|
||||
Mqtt::queue_publish(F_(message), EMSESP::webSchedulerService.computed_value); // send to MQTT if enabled
|
||||
output["api_data"] = EMSESP::webSchedulerService.computed_value; // send to API
|
||||
EMSESP::webSchedulerService.computed_value.clear();
|
||||
EMSESP::webSchedulerService.computed_value.shrink_to_fit();
|
||||
LOG_INFO("Message: %s", computed_value.c_str()); // send to log
|
||||
Mqtt::queue_publish(F_(message), computed_value); // send to MQTT if enabled
|
||||
output["api_data"] = computed_value; // send to API
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user