summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbohu <bohu@google.com>2017-02-24 12:55:39 -0800
committerbohu <bohu@google.com>2017-02-24 12:55:39 -0800
commite392ef7206d6d74b455b95f6f09d8589da69cb94 (patch)
tree7358afc71384bbd7d3440cd644741c618d27879b
parent5f2fc39bb40e1efe3bb698a44ea8daaaa8d96dcb (diff)
downloaddevice_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.h36
-rw-r--r--include/qemud.h32
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;
}