diff --git a/src/event.c b/src/event.c index 7a9bada..d9a4170 100644 --- a/src/event.c +++ b/src/event.c @@ -130,41 +130,30 @@ static int hyper_getmsg_len(struct hyper_event *he, uint32_t *len) int hyper_event_read(struct hyper_event *he, int efd) { struct hyper_buf *buf = &he->rbuf; - uint32_t len = 4; + uint32_t len = he->ops->len_offset + 4; uint8_t data[4]; - int offset = he->ops->len_offset; - int end = offset + 4; int size; int ret; fprintf(stdout, "%s\n", __func__); - while (hyper_getmsg_len(he, &len) < 0) { - size = read(he->fd, buf->data + buf->get, end - buf->get); - if (size > 0) { - buf->get += size; - fprintf(stdout, "already read %" PRIu32 " bytes data\n", - buf->get); - - if (he->ops->ack) { - /* control channel, need ack */ - hyper_set_be32(data, size); - hyper_send_msg(he->fd, NEXT, 4, data); - } - continue; + if (buf->get < len) { + size = nonblock_read(he->fd, buf->data + buf->get, len - buf->get); + if (size < 0) { + return size; } - - if (errno == EINTR) - continue; - - if (errno != EAGAIN && size != 0) { - perror("fail to read"); - return -1; + if (size > 0 && he->ops->ack) { + /* control channel, need ack */ + hyper_set_be32(data, size); + hyper_send_msg(he->fd, NEXT, 4, data); + } + buf->get += size; + if (buf->get < len) { + return 0; } - - return 0; } + hyper_getmsg_len(he, &len); fprintf(stdout, "get length %" PRIu32"\n", len); // test it with '>=' to leave at least one byte in handle(), // so that handle() can convert the data to c-string inplace. @@ -173,30 +162,17 @@ int hyper_event_read(struct hyper_event *he, int efd) return -1; } - while (buf->get < len) { - size = read(he->fd, buf->data + buf->get, len - buf->get); - if (size > 0) { - buf->get += size; - fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n", - size, buf->get); - if (he->ops->ack) { - /* control channel, need ack */ - hyper_set_be32(data, size); - hyper_send_msg(he->fd, NEXT, 4, data); - } - - continue; - } - - if (errno == EINTR) - continue; - - if (errno != EAGAIN && size != 0) { - perror("fail to read"); - return -1; - } - - /* size == 0 : No one connect to qemu socket */ + size = nonblock_read(he->fd, buf->data + buf->get, len - buf->get); + if (size < 0) { + return size; + } + if (size > 0 && he->ops->ack) { + /* control channel, need ack */ + hyper_set_be32(data, size); + hyper_send_msg(he->fd, NEXT, 4, data); + } + buf->get += size; + if (buf->get < len) { return 0; } diff --git a/src/util.c b/src/util.c index df04e3d..249706a 100644 --- a/src/util.c +++ b/src/util.c @@ -709,3 +709,25 @@ int hyper_cmd(char *cmd) return -1; } + +ssize_t nonblock_read(int fd, void *buf, size_t count) +{ + ssize_t len = 0, ret = 0; + + while (len < count) { + ret = read(fd, buf + len, count - len); + if (ret <= 0) { + if (errno == EINTR) { + continue; + } + if (errno == EAGAIN) { + ret = 0; + } + break; + } + + len += ret; + } + + return len > 0 ? len : ret; +} diff --git a/src/util.h b/src/util.h index 045a8a0..b6dc429 100644 --- a/src/util.h +++ b/src/util.h @@ -40,4 +40,5 @@ int hyper_insmod(char *module); struct passwd *hyper_getpwnam(const char *name); struct group *hyper_getgrnam(const char *name); int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups); +ssize_t nonblock_read(int fd, void *buf, size_t count); #endif