Address review: save errno before use, fix docs, add missing include

- Save errno into local before check_socket_write_err_ and HELPER_LOG
  to avoid potential clobbering between reads
- Update try_drain() doc: 0 means all-drained or no-progress (callers
  only act on -1)
- Include socket/headers.h explicitly for struct iovec
This commit is contained in:
J. Nick Koston
2026-03-16 13:08:08 -10:00
parent 69956c54a7
commit 61cc3022cb
2 changed files with 9 additions and 5 deletions
+6 -4
View File
@@ -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<uint16_t>(sent) >= total_write_len) [[likely]] {
+3 -1
View File
@@ -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);