diff --git a/esphome/components/socket/lwip_raw_tcp_impl.cpp b/esphome/components/socket/lwip_raw_tcp_impl.cpp index 566e96b2f9..5ba98dd526 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.cpp +++ b/esphome/components/socket/lwip_raw_tcp_impl.cpp @@ -535,13 +535,8 @@ void LWIPRawImpl::wait_for_data_() { } } -ssize_t LWIPRawImpl::read(void *buf, size_t len) { - // See waiting_for_data_() for safety of unlocked reads. - if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { - this->wait_for_data_(); - } - - LWIP_LOCK(); +ssize_t LWIPRawImpl::read_locked_(void *buf, size_t len) { + // Caller must hold LWIP_LOCK. Copies available data from rx_buf_ into buf. if (this->pcb_ == nullptr) { errno = ECONNRESET; return -1; @@ -600,8 +595,18 @@ ssize_t LWIPRawImpl::read(void *buf, size_t len) { return read; } +ssize_t LWIPRawImpl::read(void *buf, size_t len) { + // See waiting_for_data_() for safety of unlocked reads. + if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { + this->wait_for_data_(); + } + + LWIP_LOCK(); + return this->read_locked_(buf, len); +} + ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { - // See read() for safety analysis of these unlocked reads. + // See waiting_for_data_() for safety of unlocked reads. if (this->recv_timeout_cs_ > 0 && this->waiting_for_data_()) { this->wait_for_data_(); } @@ -609,7 +614,7 @@ ssize_t LWIPRawImpl::readv(const struct iovec *iov, int iovcnt) { LWIP_LOCK(); // Hold for entire scatter-gather operation ssize_t ret = 0; for (int i = 0; i < iovcnt; i++) { - ssize_t err = this->read(reinterpret_cast(iov[i].iov_base), iov[i].iov_len); + ssize_t err = this->read_locked_(reinterpret_cast(iov[i].iov_base), iov[i].iov_len); if (err == -1) { if (ret != 0) { // if we already read some don't return an error diff --git a/esphome/components/socket/lwip_raw_tcp_impl.h b/esphome/components/socket/lwip_raw_tcp_impl.h index 6007852692..3c27d71062 100644 --- a/esphome/components/socket/lwip_raw_tcp_impl.h +++ b/esphome/components/socket/lwip_raw_tcp_impl.h @@ -127,6 +127,7 @@ class LWIPRawImpl : public LWIPRawCommon { // authoritative recheck happens under LWIP_LOCK afterward. bool waiting_for_data_() const { return this->rx_buf_ == nullptr && !this->rx_closed_ && this->pcb_ != nullptr; } void wait_for_data_(); + ssize_t read_locked_(void *buf, size_t len); ssize_t internal_write_(const void *buf, size_t len); int internal_output_();