diff --git a/esphome/components/api/api_frame_helper.cpp b/esphome/components/api/api_frame_helper.cpp index bdc8b1be065..55ee06c41b7 100644 --- a/esphome/components/api/api_frame_helper.cpp +++ b/esphome/components/api/api_frame_helper.cpp @@ -102,8 +102,9 @@ 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) { - if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) { - HELPER_LOG("Socket write failed with errno %d", errno); + int err = errno; + if (this->check_socket_write_err_(err) != APIError::WOULD_BLOCK) { + HELPER_LOG("Socket write failed with errno %d", err); return APIError::SOCKET_WRITE_FAILED; } } @@ -135,8 +136,9 @@ 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]] { - if (this->check_socket_write_err_(errno) != APIError::WOULD_BLOCK) { - HELPER_LOG("Socket write failed with errno %d", errno); + int err = errno; + if (this->check_socket_write_err_(err) != APIError::WOULD_BLOCK) { + HELPER_LOG("Socket write failed with errno %d", err); return APIError::SOCKET_WRITE_FAILED; } } else if (static_cast(sent) >= total_write_len) [[likely]] { diff --git a/esphome/components/api/api_overflow_buffer.h b/esphome/components/api/api_overflow_buffer.h index 1bea871f570..19aae680f01 100644 --- a/esphome/components/api/api_overflow_buffer.h +++ b/esphome/components/api/api_overflow_buffer.h @@ -6,6 +6,7 @@ #include "esphome/core/defines.h" #ifdef USE_API +#include "esphome/components/socket/headers.h" #include "esphome/components/socket/socket.h" #include "esphome/core/helpers.h" @@ -52,8 +53,9 @@ class APIOverflowBuffer { uint8_t count() const { return this->count_; } /// Try to drain queued data to the socket. - /// Returns bytes-written > 0 on success/partial, 0 if all drained, + /// Returns bytes-written > 0 on success/partial, 0 if all drained or no progress, /// -1 on error (caller must check errno to distinguish EWOULDBLOCK from hard errors). + /// Callers only need to act on -1; 0 and positive values both mean "no error". /// Frees entries as they are fully sent. ssize_t try_drain(socket::Socket *socket);