A fix for Bug#850031 "Assertion failure in iproto_interact()".

Fix fiber_bread() to read at_least bytes, not
buf->len - at_least bytes, as it used to work before.
Many places that call fiber_bread rely on this.
---
 core/fiber.m         |   26 ++++++++++++++++----------
 core/log_io_remote.m |   39 ++++++++++++++-------------------------
 include/fiber.h      |    2 +-
 3 files changed, 31 insertions(+), 36 deletions(-)

diff --git a/core/fiber.m b/core/fiber.m
index 69714e3..bd21edd 100644
--- a/core/fiber.m
+++ b/core/fiber.m
@@ -665,28 +665,34 @@ read_inbox(void)
 }
 
 /**
+ * Read at least at_least bytes from a socket.
+ *
+ * @retval 0   socket is closed by the sender
+ * @reval -1   a system error
+ * @retval >0  success, size of the last read chunk is returned
+ *
  * @note: this is a cancellation point.
  */
 
-int
+ssize_t
 fiber_bread(struct tbuf *buf, size_t at_least)
 {
        ssize_t r;
        tbuf_ensure(buf, MAX(cfg.readahead, at_least));
+       size_t stop_at = buf->len + at_least;
 
        fiber_io_start(fiber->fd, EV_READ);
-       for (;;) {
+
+       while (buf->len < stop_at)
                fiber_io_yield();
+
                r = read(fiber->fd, buf->data + buf->len, buf->size - buf->len);
-               if (r > 0) {
-                       buf->len += r;
-                       if (buf->len >= at_least)
-                               break;
-               } else {
-                       if (r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
-                               continue;
+               if (r < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
+                       continue;
+               else if (r <= 0)
                        break;
-               }
+
+               buf->len += r;
        }
        fiber_io_stop(fiber->fd, EV_READ);
 
diff --git a/core/log_io_remote.m b/core/log_io_remote.m
index 41b49e6..664bdad 100644
--- a/core/log_io_remote.m
+++ b/core/log_io_remote.m
@@ -42,36 +42,25 @@
 static int
 default_remote_row_handler(struct recovery_state *r, struct tbuf *row);
 
-static u32
-row_v11_len(struct tbuf *r)
-{
-       if (r->len < sizeof(struct row_v11))
-               return 0;
-
-       if (r->len < sizeof(struct row_v11) + row_v11(r)->len)
-               return 0;
-
-       return sizeof(struct row_v11) + row_v11(r)->len;
-}
-
 static struct tbuf *
 remote_row_reader_v11()
 {
-       const int header_size = sizeof(struct row_v11);
-       struct tbuf *m;
+       ssize_t to_read = sizeof(struct row_v11) - fiber->rbuf->len;
 
-       for (;;) {
-               if (row_v11_len(fiber->rbuf) != 0) {
-                       m = tbuf_split(fiber->rbuf, row_v11_len(fiber->rbuf));
-                       say_debug("read row bytes:%" PRIu32 " %s", m->len, 
tbuf_to_hex(m));
-                       return m;
-               }
+       if (to_read > 0 && fiber_bread(fiber->rbuf, to_read) <= 0)
+               goto error;
 
-               if (fiber_bread(fiber->rbuf, header_size) <= 0) {
-                       say_error("unexpected eof reading row header");
-                       return NULL;
-               }
-       }
+       ssize_t request_len = row_v11(fiber->rbuf)->len + sizeof(struct 
row_v11);
+       to_read = request_len - fiber->rbuf->len;
+
+       if (to_read > 0 && fiber_bread(fiber->rbuf, to_read) <= 0)
+               goto error;
+
+       say_debug("read row bytes:%" PRI_SSZ, request_len);
+       return tbuf_split(fiber->rbuf, request_len);
+error:
+       say_error("unexpected eof reading row header");
+       return NULL;
 }
 
 static struct tbuf *
diff --git a/include/fiber.h b/include/fiber.h
index 8b04ab6..bd51069 100644
--- a/include/fiber.h
+++ b/include/fiber.h
@@ -148,7 +148,7 @@ void yield(void);
 void fiber_destroy_all();
 
 struct msg *read_inbox(void);
-int fiber_bread(struct tbuf *, size_t v);
+ssize_t fiber_bread(struct tbuf *, size_t v);
 
 inline static void iov_add_unsafe(const void *buf, size_t len)
 {
-- 
1.7.0.4


_______________________________________________
Mailing list: https://launchpad.net/~tarantool-developers
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~tarantool-developers
More help   : https://help.launchpad.net/ListHelp

Reply via email to