Bladeren bron

Fix handling of errors returned by writev()

Oxan van Leeuwen 2 jaren geleden
bovenliggende
commit
23e0a39a2f
1 gewijzigde bestanden met toevoegingen van 25 en 7 verwijderingen
  1. 25 7
      components/stream_server/stream_server.cpp

+ 25 - 7
components/stream_server/stream_server.cpp

@@ -137,9 +137,10 @@ void StreamServerComponent::read() {
 }
 
 void StreamServerComponent::flush() {
+    ssize_t written;
     this->buf_tail_ = this->buf_head_;
     for (Client &client : this->clients_) {
-        if (client.position == this->buf_head_)
+        if (client.disconnected || client.position == this->buf_head_)
             continue;
 
         // Split the write into two parts: from the current position to the end of the ring buffer, and from the start
@@ -149,22 +150,39 @@ void StreamServerComponent::flush() {
         iov[0].iov_len = std::min(this->buf_head_ - client.position, this->buf_ahead(client.position));
         iov[1].iov_base = &this->buf_[0];
         iov[1].iov_len = this->buf_head_ - (client.position + iov[0].iov_len);
-        client.position += client.socket->writev(iov, 2);
+        if ((written = client.socket->writev(iov, 2)) > 0) {
+            client.position += written;
+        } else if (written == 0 || errno == ECONNRESET) {
+            ESP_LOGD(TAG, "Client %s disconnected", client.identifier.c_str());
+            client.disconnected = true;
+            continue;  // don't consider this client when calculating the tail position
+        } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
+            // Expected if the (TCP) transmit buffer is full, nothing to do.
+        } else {
+            ESP_LOGE(TAG, "Failed to write to client %s with error %d!", client.identifier.c_str(), errno);
+        }
+
         this->buf_tail_ = std::min(this->buf_tail_, client.position);
     }
 }
 
 void StreamServerComponent::write() {
     uint8_t buf[128];
-    ssize_t len;
+    ssize_t read;
     for (Client &client : this->clients_) {
-        while ((len = client.socket->read(&buf, sizeof(buf))) > 0)
-            this->stream_->write_array(buf, len);
+        if (client.disconnected)
+            continue;
+
+        while ((read = client.socket->read(&buf, sizeof(buf))) > 0)
+            this->stream_->write_array(buf, read);
 
-        if (len == 0) {
+        if (read == 0 || errno == ECONNRESET) {
             ESP_LOGD(TAG, "Client %s disconnected", client.identifier.c_str());
             client.disconnected = true;
-            continue;
+        } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
+            // Expected if the (TCP) receive buffer is empty, nothing to do.
+        } else {
+            ESP_LOGW(TAG, "Failed to read from client %s with error %d!", client.identifier.c_str(), errno);
         }
     }
 }