[usb_cdc_acm] Fix EventPool/LockFreeQueue sizing off-by-one (#14894)

This commit is contained in:
J. Nick Koston
2026-03-17 12:17:43 -10:00
committed by GitHub
parent 5f06679d78
commit 97382ed814
2 changed files with 15 additions and 17 deletions
+10 -16
View File
@@ -26,16 +26,13 @@ void USBCDCACMInstance::queue_line_state_event(bool dtr, bool rts) {
event->data.line_state.dtr = dtr;
event->data.line_state.rts = rts;
if (!this->event_queue_.push(event)) {
ESP_LOGW(TAG, "Event queue full, line state event dropped (itf=%d)", this->itf_);
// Return event to pool since we couldn't queue it
this->event_pool_.release(event);
} else {
// Wake main loop immediately to process event
// Push always succeeds: pool is sized to queue capacity (SIZE-1), so if
// allocate() returned non-null, the queue cannot be full.
this->event_queue_.push(event);
#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
App.wake_loop_threadsafe();
App.wake_loop_threadsafe();
#endif
}
}
void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_bits, uint8_t parity,
@@ -53,16 +50,13 @@ void USBCDCACMInstance::queue_line_coding_event(uint32_t bit_rate, uint8_t stop_
event->data.line_coding.parity = parity;
event->data.line_coding.data_bits = data_bits;
if (!this->event_queue_.push(event)) {
ESP_LOGW(TAG, "Event queue full, line coding event dropped (itf=%d)", this->itf_);
// Return event to pool since we couldn't queue it
this->event_pool_.release(event);
} else {
// Wake main loop immediately to process event
// Push always succeeds: pool is sized to queue capacity (SIZE-1), so if
// allocate() returned non-null, the queue cannot be full.
this->event_queue_.push(event);
#if defined(USE_SOCKET_SELECT_SUPPORT) && defined(USE_WAKE_LOOP_THREADSAFE)
App.wake_loop_threadsafe();
App.wake_loop_threadsafe();
#endif
}
}
void USBCDCACMInstance::process_events_() {
+5 -1
View File
@@ -102,7 +102,11 @@ class USBCDCACMInstance : public uart::UARTComponent, public Parented<USBCDCACMC
LineStateCallback line_state_callback_{nullptr};
// Lock-free queue and event pool for cross-task event passing
EventPool<CDCEvent, EVENT_QUEUE_SIZE> event_pool_;
// Pool sized to queue capacity (SIZE-1) because LockFreeQueue<T,N> is a ring
// buffer that holds N-1 elements. This guarantees allocate() returns nullptr
// before push() can fail, preventing both a pool slot leak and an SPSC
// violation on the pool's internal free list.
EventPool<CDCEvent, EVENT_QUEUE_SIZE - 1> event_pool_;
LockFreeQueue<CDCEvent, EVENT_QUEUE_SIZE> event_queue_;
};