aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--android/android-device.c71
-rw-r--r--iolooper-select.c2
-rw-r--r--qemu-common.h13
3 files changed, 38 insertions, 48 deletions
diff --git a/android/android-device.c b/android/android-device.c
index e91185d..40ec294 100644
--- a/android/android-device.c
+++ b/android/android-device.c
@@ -597,60 +597,35 @@ _android_dev_socket_recv(AndroidDevSocket* ads, char* buf, int bufsize)
return -1;
}
- /* XXX: This is a hack that implements a blocked line read on an async
- * event socket! Redo this ASAP! */
- if (ads->type == ADS_TYPE_EVENT) {
- AndroidEventSocket* adsevent = (AndroidEventSocket*)ads;
- asyncLineReader_init(&adsevent->alr, buf, bufsize, adsevent->io);
- /* Default EOL for the line reader was '\n'. */
- asyncLineReader_setEOL(&adsevent->alr, '\0');
- AsyncStatus status = ASYNC_NEED_MORE;
-
- while (status == ASYNC_NEED_MORE) {
- status = asyncLineReader_read(&adsevent->alr);
- if (status == ASYNC_COMPLETE) {
- recvd = adsevent->alr.pos;
- break;
- } else if (status == ASYNC_ERROR) {
- if (errno == ENOMEM) {
- recvd = adsevent->alr.pos;
- } else {
- recvd = -1;
- }
- break;
- }
+ iolooper_add_read(_ads_io_looper(ads), ads->fd);
+ do {
+ int res = socket_recv(ads->fd, buf + recvd, bufsize - recvd);
+ if (res == 0) {
+ /* Disconnection. */
+ errno = ECONNRESET;
+ recvd = -1;
+ break;
}
- } else {
- iolooper_add_read(_ads_io_looper(ads), ads->fd);
- do {
- int res = socket_recv(ads->fd, buf + recvd, bufsize - recvd);
- if (res == 0) {
- /* Disconnection. */
- errno = ECONNRESET;
- recvd = -1;
- break;
+
+ if (res < 0) {
+ if (errno == EINTR) {
+ /* loop on EINTR */
+ continue;
}
- if (res < 0) {
- if (errno == EINTR) {
- /* loop on EINTR */
+ if (errno == EWOULDBLOCK || errno == EAGAIN) {
+ res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline);
+ if (res > 0) {
+ /* Ready to read. */
continue;
}
-
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- res = iolooper_wait_absolute(_ads_io_looper(ads), ads->deadline);
- if (res > 0) {
- /* Ready to read. */
- continue;
- }
- }
- recvd = -1;
- break;
}
- recvd += res;
- } while (recvd < bufsize);
- iolooper_del_read(_ads_io_looper(ads), ads->fd);
- }
+ recvd = -1;
+ break;
+ }
+ recvd += res;
+ } while (recvd < bufsize);
+ iolooper_del_read(_ads_io_looper(ads), ads->fd);
/* In case of an I/O failure we have to invoke failure callback. Note that we
* report I/O failures only on registered sockets. */
diff --git a/iolooper-select.c b/iolooper-select.c
index 955204d..5024c9a 100644
--- a/iolooper-select.c
+++ b/iolooper-select.c
@@ -175,6 +175,8 @@ iolooper_wait( IoLooper* iol, int64_t duration )
if (count == 0)
return 0;
+ CLAMP_MAC_TIMEOUT(duration);
+
if (duration < 0)
tm = NULL;
else {
diff --git a/qemu-common.h b/qemu-common.h
index 897d510..79ac779 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -395,4 +395,17 @@ typedef enum DisplayType
DT_NOGRAPHIC,
} DisplayType;
+/*
+ * A fixer for timeout value passed to select() on Mac. The issue is that Mac's
+ * version of select() will return EINVAL on timeouts larger than 100000000
+ * seconds, even though it should have just clamped it. So, for Mac we should
+ * make sure that timeout value is bound to 100000000 seconds before passing it
+ * to select().
+ */
+#if _DARWIN_C_SOURCE
+#define CLAMP_MAC_TIMEOUT(to) do { if (to > 100000000000LL) to = 100000000000LL; } while (0)
+#else
+#define CLAMP_MAC_TIMEOUT(to) ((void)0)
+#endif // _DARWIN_C_SOURCE
+
#endif