From 3ac6eb0f5a95b54720dd6abc9707c27198b31601 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 16 Mar 2026 13:01:42 -1000 Subject: [PATCH] Address review: only log hard errors, fix try_drain doc comments - Move HELPER_LOG after errno check so transient WOULD_BLOCK doesn't spam very-verbose logs during normal backpressure - Fix try_drain() docstring: -1 can be EWOULDBLOCK or hard error (caller distinguishes via errno), 0 means no progress (not would-block) --- esphome/components/api/api_frame_helper.cpp | 10 ++++++---- esphome/components/api/api_overflow_buffer.cpp | 3 ++- esphome/components/api/api_overflow_buffer.h | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index ec326edbd6..bdc8b1be06 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -102,9 +102,10 @@ const LogString *api_error_to_logstr(APIError err) { APIError APIFrameHelper::drain_overflow_and_handle_errors_() { if (this->overflow_buf_.try_drain(this->socket_.get()) == -1) { - HELPER_LOG("Socket write failed with errno %d", errno); - if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) + if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) { + HELPER_LOG("Socket write failed with errno %d", errno); return APIError::SOCKET_WRITE_FAILED; + } } return APIError::OK; } @@ -134,9 +135,10 @@ APIError APIFrameHelper::write_raw_(const struct iovec *iov, int iovcnt, uint16_ (iovcnt == 1) ? this->socket_->write(iov[0].iov_base, iov[0].iov_len) : this->socket_->writev(iov, iovcnt); if (sent == -1) [[unlikely]] { - HELPER_LOG("Socket write failed with errno %d", errno); - if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) + if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) { + HELPER_LOG("Socket write failed with errno %d", errno); return APIError::SOCKET_WRITE_FAILED; + } } else if (static_cast(sent) >= total_write_len) [[likely]] { return APIError::OK; } else { diff --git a/esphome/components/api/api_overflow_buffer.cpp b/esphome/components/api/api_overflow_buffer.cpp index af3b670e0e..e242d4553e 100644 --- a/esphome/components/api/api_overflow_buffer.cpp +++ b/esphome/components/api/api_overflow_buffer.cpp @@ -18,7 +18,8 @@ ssize_t APIOverflowBuffer::try_drain(socket::Socket *socket) { ssize_t sent = socket->write(front->current_data(), front->remaining()); if (sent <= 0) { - // -1 = error (caller checks errno), 0 = would block + // -1 = error (caller checks errno for EWOULDBLOCK vs hard error) + // 0 = nothing sent (treat as no progress) return sent; } diff --git a/esphome/components/api/api_overflow_buffer.h b/esphome/components/api/api_overflow_buffer.h index cd26bcdb8b..1bea871f57 100644 --- a/esphome/components/api/api_overflow_buffer.h +++ b/esphome/components/api/api_overflow_buffer.h @@ -52,7 +52,8 @@ class APIOverflowBuffer { uint8_t count() const { return this->count_; } /// Try to drain queued data to the socket. - /// Returns bytes-written >= 0 on success/partial, -1 on hard error (errno set). + /// Returns bytes-written > 0 on success/partial, 0 if all drained, + /// -1 on error (caller must check errno to distinguish EWOULDBLOCK from hard errors). /// Frees entries as they are fully sent. ssize_t try_drain(socket::Socket *socket);