mirror of
https://github.com/esphome/esphome.git
synced 2026-03-23 22:37:31 +08:00
[openthread] Guard InstanceLock against uninitialized semaphore (#14940)
Some checks failed
CI for docker images / Build docker containers (docker, ubuntu-24.04) (push) Has been cancelled
CI for docker images / Build docker containers (docker, ubuntu-24.04-arm) (push) Has been cancelled
CI for docker images / Build docker containers (ha-addon, ubuntu-24.04) (push) Has been cancelled
CI for docker images / Build docker containers (ha-addon, ubuntu-24.04-arm) (push) Has been cancelled
CI / Create common environment (push) Has been cancelled
CI / Check pylint (push) Has been cancelled
CI / Run script/ci-custom (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.11) (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.14) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.11) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.13) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.14) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.11) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.14) (push) Has been cancelled
CI / Determine which jobs to run (push) Has been cancelled
CI / Run integration tests (push) Has been cancelled
CI / Run C++ unit tests (push) Has been cancelled
CI / Run CodSpeed benchmarks (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 IDF (push) Has been cancelled
CI / Run script/clang-tidy for ESP8266 (push) Has been cancelled
CI / Run script/clang-tidy for ZEPHYR (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 1/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 2/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 3/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 4/4 (push) Has been cancelled
CI / Test components batch (${{ matrix.components }}) (push) Has been cancelled
CI / pre-commit.ci lite (push) Has been cancelled
CI / Build target branch for memory impact (push) Has been cancelled
CI / Build PR branch for memory impact (push) Has been cancelled
CI / Comment memory impact (push) Has been cancelled
CI / CI Status (push) Has been cancelled
Synchronise Device Classes from Home Assistant / Sync Device Classes (push) Has been cancelled
Some checks failed
CI for docker images / Build docker containers (docker, ubuntu-24.04) (push) Has been cancelled
CI for docker images / Build docker containers (docker, ubuntu-24.04-arm) (push) Has been cancelled
CI for docker images / Build docker containers (ha-addon, ubuntu-24.04) (push) Has been cancelled
CI for docker images / Build docker containers (ha-addon, ubuntu-24.04-arm) (push) Has been cancelled
CI / Create common environment (push) Has been cancelled
CI / Check pylint (push) Has been cancelled
CI / Run script/ci-custom (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.11) (push) Has been cancelled
CI / Run pytest (macOS-latest, 3.14) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.11) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.13) (push) Has been cancelled
CI / Run pytest (ubuntu-latest, 3.14) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.11) (push) Has been cancelled
CI / Run pytest (windows-latest, 3.14) (push) Has been cancelled
CI / Determine which jobs to run (push) Has been cancelled
CI / Run integration tests (push) Has been cancelled
CI / Run C++ unit tests (push) Has been cancelled
CI / Run CodSpeed benchmarks (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 IDF (push) Has been cancelled
CI / Run script/clang-tidy for ESP8266 (push) Has been cancelled
CI / Run script/clang-tidy for ZEPHYR (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 1/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 2/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 3/4 (push) Has been cancelled
CI / Run script/clang-tidy for ESP32 Arduino 4/4 (push) Has been cancelled
CI / Test components batch (${{ matrix.components }}) (push) Has been cancelled
CI / pre-commit.ci lite (push) Has been cancelled
CI / Build target branch for memory impact (push) Has been cancelled
CI / Build PR branch for memory impact (push) Has been cancelled
CI / Comment memory impact (push) Has been cancelled
CI / CI Status (push) Has been cancelled
Synchronise Device Classes from Home Assistant / Sync Device Classes (push) Has been cancelled
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
#include <openthread/instance.h>
|
||||
#include <openthread/thread.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
@@ -28,6 +29,8 @@ class OpenThreadComponent : public Component {
|
||||
float get_setup_priority() const override { return setup_priority::WIFI; }
|
||||
|
||||
bool is_connected() const { return this->connected_; }
|
||||
/// Returns true once esp_openthread_init() has completed and the OT lock is usable.
|
||||
bool is_lock_initialized() const { return this->lock_initialized_; }
|
||||
network::IPAddresses get_ip_addresses();
|
||||
std::optional<otIp6Address> get_omr_address();
|
||||
void ot_main();
|
||||
@@ -51,6 +54,7 @@ class OpenThreadComponent : public Component {
|
||||
uint32_t poll_period_{0};
|
||||
#endif
|
||||
std::optional<int8_t> output_power_{};
|
||||
std::atomic<bool> lock_initialized_{false};
|
||||
bool teardown_started_{false};
|
||||
bool teardown_complete_{false};
|
||||
bool connected_{false};
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "esp_openthread_lock.h"
|
||||
|
||||
#include "esp_task_wdt.h"
|
||||
#include "esphome/core/hal.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
||||
@@ -81,6 +82,9 @@ void OpenThreadComponent::ot_main() {
|
||||
// Initialize the OpenThread stack
|
||||
// otLoggingSetLevel(OT_LOG_LEVEL_DEBG);
|
||||
ESP_ERROR_CHECK(esp_openthread_init(&config));
|
||||
// Mark lock as initialized so InstanceLock callers know it's safe to acquire.
|
||||
// Must be set after esp_openthread_init() which creates the internal semaphore.
|
||||
this->lock_initialized_ = true;
|
||||
// Fetch OT instance once to avoid repeated call into OT stack
|
||||
otInstance *instance = esp_openthread_get_instance();
|
||||
|
||||
@@ -180,7 +184,8 @@ void OpenThreadComponent::ot_main() {
|
||||
|
||||
esp_openthread_launch_mainloop();
|
||||
|
||||
// Clean up
|
||||
// Clean up - reset lock flag before deinit destroys the semaphore
|
||||
this->lock_initialized_ = false;
|
||||
esp_openthread_deinit();
|
||||
esp_openthread_netif_glue_deinit();
|
||||
esp_netif_destroy(openthread_netif);
|
||||
@@ -210,6 +215,9 @@ network::IPAddresses OpenThreadComponent::get_ip_addresses() {
|
||||
otInstance *OpenThreadComponent::get_openthread_instance_() { return esp_openthread_get_instance(); }
|
||||
|
||||
std::optional<InstanceLock> InstanceLock::try_acquire(int delay) {
|
||||
if (!global_openthread_component->is_lock_initialized()) {
|
||||
return {};
|
||||
}
|
||||
if (esp_openthread_lock_acquire(delay)) {
|
||||
return InstanceLock();
|
||||
}
|
||||
@@ -217,6 +225,18 @@ std::optional<InstanceLock> InstanceLock::try_acquire(int delay) {
|
||||
}
|
||||
|
||||
InstanceLock InstanceLock::acquire() {
|
||||
// Wait for the lock to be created by ot_main() before attempting to acquire it.
|
||||
// esp_openthread_lock_acquire() will assert-crash if called before esp_openthread_init().
|
||||
constexpr uint32_t lock_init_timeout_ms = 10000;
|
||||
uint32_t start = millis();
|
||||
while (!global_openthread_component->is_lock_initialized()) {
|
||||
if (millis() - start > lock_init_timeout_ms) {
|
||||
ESP_LOGE(TAG, "OpenThread lock not initialized after %" PRIu32 "ms, aborting", lock_init_timeout_ms);
|
||||
abort();
|
||||
}
|
||||
delay(10);
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
while (!esp_openthread_lock_acquire(100)) {
|
||||
esp_task_wdt_reset();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user