From 0c71cdee96971283c845423622d3d86bac787c89 Mon Sep 17 00:00:00 2001 From: Amit Shah Date: Thu, 13 Jan 2011 19:13:50 +0530 Subject: auto-virtserial: Ensure we handle EINTR/EAGAIN on local file descriptors For the guest and host file send functions, we could get EINTR or EAGAIN on local file descriptors. Ensure we handle that. Also, add a timeout to read() on the local descriptor to ensure we don't block forever on a guest that gets stuck. Signed-off-by: Amit Shah --- auto-virtserial.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/auto-virtserial.c b/auto-virtserial.c index 03c3090..560a3e4 100644 --- a/auto-virtserial.c +++ b/auto-virtserial.c @@ -1097,8 +1097,18 @@ static int test_host_file_send(int nr) guest_cmd_only(&gpkt); /* The guest now is waiting for our data */ - while ((ret = read(fd, buf, BUF_LENGTH))) + while (1) { + ret = read(fd, buf, BUF_LENGTH); + if (ret < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + else if (ret < 0) { + fprintf(stderr, "read error %d\n", errno); + break; + } + if (ret == 0) + break; write(chardevs[nr].sock, buf, ret); + } close(fd); /* guest will stop reading only if read() returns 0 */ @@ -1180,6 +1190,7 @@ static int test_guest_file_send(int nr) { char buf[BUF_LENGTH]; char csum[BUF_LENGTH]; + struct pollfd pollfds[1]; struct guest_packet gpkt; int err, ret, fd, csum_fd; @@ -1210,7 +1221,24 @@ static int test_guest_file_send(int nr) guest_cmd_only(&gpkt); /* The guest now is sending us data */ - while ((ret = read(chardevs[nr].sock, buf, BUF_LENGTH))) { + pollfds[0].fd = chardevs[nr].sock; + pollfds[0].events = POLLIN; + while (1) { + /* If no response received for 5s, assume guest is stuck. */ + ret = poll(pollfds, 1, 5000); + if (ret <= 0) { + debug("poll returned %d\n", ret); + break; + } + ret = read(chardevs[nr].sock, buf, BUF_LENGTH); + if (ret == 0) + break; + if (ret < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + else if (ret < 0) { + fprintf(stderr, "read error %d\n", errno); + break; + } write(fd, buf, ret); if (ret > 0 && ret < BUF_LENGTH) break; -- cgit