From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54865) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1anNd5-0003ZM-Oq for qemu-devel@nongnu.org; Tue, 05 Apr 2016 05:50:36 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1anNd3-0001B1-E3 for qemu-devel@nongnu.org; Tue, 05 Apr 2016 05:50:35 -0400 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]:33286) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1anNd3-0001Ar-6p for qemu-devel@nongnu.org; Tue, 05 Apr 2016 05:50:33 -0400 Received: by mail-wm0-x241.google.com with SMTP id i204so2688754wmd.0 for ; Tue, 05 Apr 2016 02:50:33 -0700 (PDT) Sender: Paolo Bonzini From: Paolo Bonzini Date: Tue, 5 Apr 2016 11:50:11 +0200 Message-Id: <1459849818-26649-9-git-send-email-pbonzini@redhat.com> In-Reply-To: <1459849818-26649-1-git-send-email-pbonzini@redhat.com> References: <1459849818-26649-1-git-send-email-pbonzini@redhat.com> Subject: [Qemu-devel] [PULL 08/15] char: fix broken EAGAIN retry on OS-X due to errno clobbering List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Paolo Bonzini From: "Daniel P. Berrange" Some of the chardev I/O paths really want to write the complete data buffer even though the channel is in non-blocking mode. To achieve this they look for EAGAIN and g_usleep() for 100ms. Unfortunately the code is set to check errno == EAGAIN a second time, after the g_usleep() call has completed. On OS-X at least, g_usleep clobbers errno to ETIMEDOUT, causing the retry to be skipped. This failure to retry means the full data isn't written to the chardev backend, which causes various failures including making the tests/ahci-test qtest hang. Rather than playing games trying to reset errno just simplify the code to use a goto to retry instead of a a loop. Signed-off-by: Daniel P. Berrange Message-Id: <1459438168-8146-2-git-send-email-berrange@redhat.com> Signed-off-by: Paolo Bonzini --- qemu-char.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/qemu-char.c b/qemu-char.c index 270819a..93fd733 100644 --- a/qemu-char.c +++ b/qemu-char.c @@ -225,12 +225,12 @@ static void qemu_chr_fe_write_log(CharDriverState *s, } while (done < len) { - do { - ret = write(s->logfd, buf + done, len - done); - if (ret == -1 && errno == EAGAIN) { - g_usleep(100); - } - } while (ret == -1 && errno == EAGAIN); + retry: + ret = write(s->logfd, buf + done, len - done); + if (ret == -1 && errno == EAGAIN) { + g_usleep(100); + goto retry; + } if (ret <= 0) { return; @@ -246,12 +246,12 @@ static int qemu_chr_fe_write_buffer(CharDriverState *s, const uint8_t *buf, int qemu_mutex_lock(&s->chr_write_lock); while (*offset < len) { - do { - res = s->chr_write(s, buf + *offset, len - *offset); - if (res == -1 && errno == EAGAIN) { - g_usleep(100); - } - } while (res == -1 && errno == EAGAIN); + retry: + res = s->chr_write(s, buf + *offset, len - *offset); + if (res < 0 && errno == EAGAIN) { + g_usleep(100); + goto retry; + } if (res <= 0) { break; @@ -333,12 +333,12 @@ int qemu_chr_fe_read_all(CharDriverState *s, uint8_t *buf, int len) } while (offset < len) { - do { - res = s->chr_sync_read(s, buf + offset, len - offset); - if (res == -1 && errno == EAGAIN) { - g_usleep(100); - } - } while (res == -1 && errno == EAGAIN); + retry: + res = s->chr_sync_read(s, buf + offset, len - offset); + if (res == -1 && errno == EAGAIN) { + g_usleep(100); + goto retry; + } if (res == 0) { break; -- 2.5.5