[Spice-devel] [PATCH spice-streaming-agent v3 2/5] Fix reading from a closed virtio port

Lukáš Hrázký lhrazky at redhat.com
Fri May 18 12:32:06 UTC 2018


Reading from a closed virtio port looped indefinitely, check the read()
returning 0 and throw an exception if it happens.

Signed-off-by: Lukáš Hrázký <lhrazky at redhat.com>
---
 src/error.hpp                      |  2 ++
 src/stream-port.cpp                |  4 ++++
 src/unittests/test-stream-port.cpp | 12 ++++++++++++
 3 files changed, 18 insertions(+)

diff --git a/src/error.hpp b/src/error.hpp
index 333a481..e30990f 100644
--- a/src/error.hpp
+++ b/src/error.hpp
@@ -24,6 +24,8 @@ public:
 class IOError : public Error
 {
 public:
+    using Error::Error;
+
     IOError(const std::string &msg, int sys_errno);
 };
 
diff --git a/src/stream-port.cpp b/src/stream-port.cpp
index cee63ac..c536642 100644
--- a/src/stream-port.cpp
+++ b/src/stream-port.cpp
@@ -22,6 +22,10 @@ void read_all(int fd, void *buf, size_t len)
     while (len > 0) {
         ssize_t n = read(fd, buf, len);
 
+        if (n == 0) {
+            throw ReadError("Reading message from device failed: read() returned 0, device is closed.");
+        }
+
         if (n < 0) {
             if (errno == EINTR) {
                 continue;
diff --git a/src/unittests/test-stream-port.cpp b/src/unittests/test-stream-port.cpp
index 688fa2b..a337344 100644
--- a/src/unittests/test-stream-port.cpp
+++ b/src/unittests/test-stream-port.cpp
@@ -9,6 +9,7 @@
 #include <sys/socket.h>
 
 #include "stream-port.hpp"
+#include "error.hpp"
 
 
 namespace ssa = spice::streaming_agent;
@@ -48,6 +49,17 @@ SCENARIO("test basic IO on the stream port", "[port][io]") {
             CHECK(std::string(buf, src_size) == src_buf);
         }
 
+        WHEN("closing the remote end and trying to read") {
+            CHECK(write(fd[0], src_buf, src_size) == src_size);
+            char buf[10];
+            ssa::read_all(fd[1], buf, 3);
+            CHECK(std::string(buf, 3) == "bre");
+            CHECK(close(fd[0]) == 0);
+            ssa::read_all(fd[1], buf, 4);
+            CHECK(std::string(buf, 4) == "keke");
+            CHECK_THROWS_AS(ssa::read_all(fd[1], buf, 1), ssa::ReadError);
+        }
+
         // clean up the descriptors in case they are still open
         close(fd[0]);
         close(fd[1]);
-- 
2.16.2



More information about the Spice-devel mailing list