diff options
author | bohu <bohu@google.com> | 2017-02-24 12:55:39 -0800 |
---|---|---|
committer | bohu <bohu@google.com> | 2017-02-24 12:55:39 -0800 |
commit | e392ef7206d6d74b455b95f6f09d8589da69cb94 (patch) | |
tree | 7358afc71384bbd7d3440cd644741c618d27879b | |
parent | 5f2fc39bb40e1efe3bb698a44ea8daaaa8d96dcb (diff) | |
download | device_generic_goldfish-e392ef7206d6d74b455b95f6f09d8589da69cb94.tar.gz device_generic_goldfish-e392ef7206d6d74b455b95f6f09d8589da69cb94.tar.bz2 device_generic_goldfish-e392ef7206d6d74b455b95f6f09d8589da69cb94.zip |
Emulator: handle partial read and write in qemu pipe functions
When partial read or write happens, the services that depend on
qemu pipe will be flaky.
This CL checks for partial read or write, and retries the rest, unless
there is hard failure.
Change-Id: I3ebeee3f57672a8ae07236a7e53e9d0eee09f4fc
-rw-r--r-- | include/qemu_pipe.h | 36 | ||||
-rw-r--r-- | include/qemud.h | 32 |
2 files changed, 33 insertions, 35 deletions
diff --git a/include/qemu_pipe.h b/include/qemu_pipe.h index 53aec97a..d76ba3b9 100644 --- a/include/qemu_pipe.h +++ b/include/qemu_pipe.h @@ -30,6 +30,30 @@ # define D(...) do{}while(0) #endif +static bool ReadFully(int fd, void* data, size_t byte_count) { + uint8_t* p = (uint8_t*)(data); + size_t remaining = byte_count; + while (remaining > 0) { + ssize_t n = TEMP_FAILURE_RETRY(read(fd, p, remaining)); + if (n <= 0) return false; + p += n; + remaining -= n; + } + return true; +} + +static bool WriteFully(int fd, const void* data, size_t byte_count) { + const uint8_t* p = (const uint8_t*)(data); + size_t remaining = byte_count; + while (remaining > 0) { + ssize_t n = TEMP_FAILURE_RETRY(write(fd, p, remaining)); + if (n == -1) return false; + p += n; + remaining -= n; + } + return true; +} + /* Try to open a new Qemu fast-pipe. This function returns a file descriptor * that can be used to communicate with a named service managed by the * emulator. @@ -66,9 +90,9 @@ qemu_pipe_open(const char* pipeName) snprintf(buff, sizeof buff, "pipe:%s", pipeName); - fd = open("/dev/qemu_pipe", O_RDWR); + fd = TEMP_FAILURE_RETRY(open("/dev/qemu_pipe", O_RDWR)); if (fd < 0 && errno == ENOENT) - fd = open("/dev/goldfish_pipe", O_RDWR); + fd = TEMP_FAILURE_RETRY(open("/dev/goldfish_pipe", O_RDWR)); if (fd < 0) { D("%s: Could not open /dev/qemu_pipe: %s", __FUNCTION__, strerror(errno)); //errno = ENOSYS; @@ -77,14 +101,8 @@ qemu_pipe_open(const char* pipeName) buffLen = strlen(buff); - ret = TEMP_FAILURE_RETRY(write(fd, buff, buffLen+1)); - if (ret != buffLen+1) { + if (!WriteFully(fd, buff, buffLen + 1)) { D("%s: Could not connect to %s pipe service: %s", __FUNCTION__, pipeName, strerror(errno)); - if (ret == 0) { - errno = ECONNRESET; - } else if (ret > 0) { - errno = EINVAL; - } return -1; } diff --git a/include/qemud.h b/include/qemud.h index ccc7b1e3..71ec3bf2 100644 --- a/include/qemud.h +++ b/include/qemud.h @@ -39,26 +39,6 @@ # define D(...) ((void)0) static __inline__ int -qemud_fd_write(int fd, const void* buff, int len) -{ - int len2; - do { - len2 = write(fd, buff, len); - } while (len2 < 0 && errno == EINTR); - return len2; -} - -static __inline__ int -qemud_fd_read(int fd, void* buff, int len) -{ - int len2; - do { - len2 = read(fd, buff, len); - } while (len2 < 0 && errno == EINTR); - return len2; -} - -static __inline__ int qemud_channel_open(const char* name) { int fd; @@ -82,7 +62,7 @@ qemud_channel_open(const char* name) } /* send service name to connect */ - if (qemud_fd_write(fd, name, namelen) != namelen) { + if (!WriteFully(fd, name, namelen)) { D("can't send service name to qemud: %s", strerror(errno)); close(fd); @@ -90,7 +70,7 @@ qemud_channel_open(const char* name) } /* read answer from daemon */ - if (qemud_fd_read(fd, answer, 2) != 2 || + if (!ReadFully(fd, answer, 2) || answer[0] != 'O' || answer[1] != 'K') { D("cant' connect to %s service through qemud", name); close(fd); @@ -112,12 +92,12 @@ qemud_channel_send(int fd, const void* msg, int msglen) return 0; snprintf(header, sizeof header, "%04x", msglen); - if (qemud_fd_write(fd, header, 4) != 4) { + if (!WriteFully(fd, header, 4)) { D("can't write qemud frame header: %s", strerror(errno)); return -1; } - if (qemud_fd_write(fd, msg, msglen) != msglen) { + if (!WriteFully(fd, msg, msglen)) { D("can4t write qemud frame payload: %s", strerror(errno)); return -1; } @@ -130,7 +110,7 @@ qemud_channel_recv(int fd, void* msg, int msgsize) char header[5]; int size, avail; - if (qemud_fd_read(fd, header, 4) != 4) { + if (!ReadFully(fd, header, 4)) { D("can't read qemud frame header: %s", strerror(errno)); return -1; } @@ -142,7 +122,7 @@ qemud_channel_recv(int fd, void* msg, int msgsize) if (size > msgsize) return -1; - if (qemud_fd_read(fd, msg, size) != size) { + if (!ReadFully(fd, msg, size)) { D("can't read qemud frame payload: %s", strerror(errno)); return -1; } |