mirror of
https://github.com/esphome/esphome.git
synced 2026-08-22 22:26:21 +00:00
[nextion] Fix unbounded queue growth and OOM crash when display sends no data (#17553)
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#include "nextion.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <new>
|
||||
|
||||
#include "esphome/core/application.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
@@ -354,6 +355,7 @@ void Nextion::loop() {
|
||||
|
||||
this->process_serial_(); // Receive serial data
|
||||
this->process_nextion_commands_(); // Process nextion return commands
|
||||
this->purge_stale_queue_entries_(); // Drop expired entries even when the display sends no data
|
||||
|
||||
if (!this->connection_state_.nextion_reports_is_setup_) {
|
||||
if (this->started_ms_ == 0)
|
||||
@@ -902,6 +904,11 @@ void Nextion::process_nextion_commands_() {
|
||||
this->command_data_.erase(0, to_process_length + DELIMITER_SIZE + 1);
|
||||
}
|
||||
|
||||
ESP_LOGN(TAG, "Loop end");
|
||||
this->process_serial_();
|
||||
} // Nextion::process_nextion_commands_()
|
||||
|
||||
void Nextion::purge_stale_queue_entries_() {
|
||||
const uint32_t ms = App.get_loop_component_start_time();
|
||||
|
||||
if (this->max_q_age_ms_ > 0 && !this->nextion_queue_.empty() &&
|
||||
@@ -927,10 +934,7 @@ void Nextion::process_nextion_commands_() {
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGN(TAG, "Loop end");
|
||||
// App.feed_wdt(); Remove before master merge
|
||||
this->process_serial_();
|
||||
} // Nextion::process_nextion_commands_()
|
||||
}
|
||||
|
||||
void Nextion::set_nextion_sensor_state(int queue_type, const std::string &name, float state) {
|
||||
this->set_nextion_sensor_state(static_cast<NextionQueueType>(queue_type), name, state);
|
||||
@@ -1101,7 +1105,13 @@ void Nextion::add_no_result_to_queue_(const std::string &variable_name) {
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
// NOLINTNEXTLINE(cppcoreguidelines-owning-memory)
|
||||
nextion_queue->component = new nextion::NextionComponentBase;
|
||||
nextion_queue->component = new (std::nothrow) nextion::NextionComponentBase;
|
||||
if (nextion_queue->component == nullptr) {
|
||||
ESP_LOGW(TAG, "Component alloc failed");
|
||||
nextion_queue->~NextionQueue();
|
||||
allocator.deallocate(nextion_queue, 1);
|
||||
return;
|
||||
}
|
||||
nextion_queue->component->set_variable_name(variable_name);
|
||||
|
||||
nextion_queue->queue_time = App.get_loop_component_start_time();
|
||||
@@ -1157,7 +1167,13 @@ void Nextion::add_no_result_to_queue_with_pending_command_(const std::string &va
|
||||
}
|
||||
new (nextion_queue) nextion::NextionQueue();
|
||||
|
||||
nextion_queue->component = new nextion::NextionComponentBase;
|
||||
nextion_queue->component = new (std::nothrow) nextion::NextionComponentBase;
|
||||
if (nextion_queue->component == nullptr) {
|
||||
ESP_LOGW(TAG, "Component alloc failed");
|
||||
nextion_queue->~NextionQueue();
|
||||
allocator.deallocate(nextion_queue, 1);
|
||||
return;
|
||||
}
|
||||
nextion_queue->component->set_variable_name(variable_name);
|
||||
nextion_queue->queue_time = App.get_loop_component_start_time();
|
||||
nextion_queue->pending_command = command; // Store command for retry
|
||||
|
||||
@@ -1486,6 +1486,10 @@ class Nextion final : public NextionBase, public PollingComponent, public uart::
|
||||
|
||||
void process_nextion_commands_();
|
||||
void process_serial_();
|
||||
/// Drop queue entries older than max_q_age_ms_. Called from loop() so it also runs when the
|
||||
/// display sends no data at all (disconnected or asleep), which would otherwise grow the queue
|
||||
/// without bound.
|
||||
void purge_stale_queue_entries_();
|
||||
uint16_t touch_sleep_timeout_ = 0;
|
||||
uint8_t wake_up_page_ = 255;
|
||||
#ifdef USE_NEXTION_CONF_START_UP_PAGE
|
||||
|
||||
Reference in New Issue
Block a user