diff options
-rw-r--r-- | android/android-device.c | 71 | ||||
-rw-r--r-- | iolooper-select.c | 2 | ||||
-rw-r--r-- | qemu-common.h | 13 |
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 |