Files
esphome/tests/integration/fixtures/logger_buffered_recursion_guard.yaml

62 lines
2.6 KiB
YAML

esphome:
name: logger-recursion-test
host:
api:
logger:
level: DEBUG
on_message:
# Fires on the main loop for every message delivered to listeners, including
# messages drained from the task log buffer (i.e. logged from a non-main thread).
# The lambda logs again on the main task. Without a recursion guard on the buffered
# drain path this re-entrant log reuses the shared tx_buffer_ and clobbers the
# buffered message that is still being delivered, corrupting its console output.
- level: VERY_VERBOSE
then:
- lambda: |-
ESP_LOGD("reentry", "REENTRANT_CLOBBER_MARKER");
button:
- platform: template
name: "Start Race Test"
id: start_test_button
on_press:
- lambda: |-
// Keep the count well under the host task-log-buffer slot count so every
// message goes through the ring buffer (buffered drain path) instead of the
// emergency console fallback. The main loop is blocked in pthread_join while
// the thread logs, so all messages are drained together once it returns.
static const int NUM_MESSAGES = 30;
struct ThreadTest {
static void *thread_func(void *arg) {
char thread_name[16];
snprintf(thread_name, sizeof(thread_name), "LogThread");
#ifdef __APPLE__
pthread_setname_np(thread_name);
#else
pthread_setname_np(pthread_self(), thread_name);
#endif
for (int i = 0; i < NUM_MESSAGES; i++) {
// Verifiable payload: data is a deterministic function of the message
// index, so a clobbered buffer shows up as a missing or mismatched line.
ESP_LOGD("thread_test", "THREADMSG%03d_DATA_%08X", i, i * 12345);
}
return nullptr;
}
};
// RACE_TEST_START / RACE_TEST_COMPLETE are logged from the main task (the
// synchronous path, which already holds the recursion guard) so the test can
// always detect completion even when the buffered path is corrupted.
ESP_LOGI("thread_test", "RACE_TEST_START: logging %d messages from a thread", NUM_MESSAGES);
pthread_t thread;
if (pthread_create(&thread, nullptr, ThreadTest::thread_func, nullptr) != 0) {
ESP_LOGE("thread_test", "RACE_TEST_ERROR: Failed to create thread");
return;
}
pthread_join(thread, nullptr);
ESP_LOGI("thread_test", "RACE_TEST_COMPLETE: thread finished, expected %d messages", NUM_MESSAGES);