diff --git a/src/irda.c b/src/irda.c index 02217e3..2271a69 100644 --- a/src/irda.c +++ b/src/irda.c @@ -36,6 +36,7 @@ #include // irda #include // select #include // ioctl + #include #endif #include "irda.h" @@ -47,6 +48,7 @@ typedef int s_ssize_t; typedef DWORD s_errcode_t; #define S_ERRNO WSAGetLastError () +#define S_EINTR WSAEINTR #define S_EAGAIN WSAEWOULDBLOCK #define S_ENOMEM WSA_NOT_ENOUGH_MEMORY #define S_EINVAL WSAEINVAL @@ -59,6 +61,7 @@ typedef DWORD s_errcode_t; typedef ssize_t s_ssize_t; typedef int s_errcode_t; #define S_ERRNO errno +#define S_EINTR EINTR #define S_EAGAIN EAGAIN #define S_ENOMEM ENOMEM #define S_EINVAL EINVAL @@ -408,20 +411,24 @@ dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual) goto out_invalidargs; } - struct timeval tv; - if (device->timeout >= 0) { - tv.tv_sec = (device->timeout / 1000); - tv.tv_usec = (device->timeout % 1000) * 1000; - } - - fd_set fds; - FD_ZERO (&fds); - FD_SET (device->fd, &fds); - while (nbytes < size) { - int rc = select (device->fd + 1, &fds, NULL, NULL, (device->timeout >= 0 ? &tv : NULL)); + fd_set fds; + FD_ZERO (&fds); + FD_SET (device->fd, &fds); + + struct timeval tvt; + if (device->timeout > 0) { + tvt.tv_sec = (device->timeout / 1000); + tvt.tv_usec = (device->timeout % 1000) * 1000; + } else if (device->timeout == 0) { + timerclear (&tvt); + } + + int rc = select (device->fd + 1, &fds, NULL, NULL, device->timeout >= 0 ? &tvt : NULL); if (rc < 0) { s_errcode_t errcode = S_ERRNO; + if (errcode == S_EINTR) + continue; // Retry. SYSERROR (device->context, errcode); status = syserror(errcode); goto out; @@ -432,6 +439,8 @@ dc_irda_read (dc_irda_t *device, void *data, size_t size, size_t *actual) s_ssize_t n = recv (device->fd, (char*) data + nbytes, size - nbytes, 0); if (n < 0) { s_errcode_t errcode = S_ERRNO; + if (errcode == S_EINTR || errcode == S_EAGAIN) + continue; // Retry. SYSERROR (device->context, errcode); status = syserror(errcode); goto out; @@ -468,12 +477,32 @@ dc_irda_write (dc_irda_t *device, const void *data, size_t size, size_t *actual) } while (nbytes < size) { - s_ssize_t n = send (device->fd, (char*) data + nbytes, size - nbytes, 0); - if (n < 0) { + fd_set fds; + FD_ZERO (&fds); + FD_SET (device->fd, &fds); + + int rc = select (device->fd + 1, NULL, &fds, NULL, NULL); + if (rc < 0) { s_errcode_t errcode = S_ERRNO; + if (errcode == S_EINTR) + continue; // Retry. SYSERROR (device->context, errcode); status = syserror(errcode); goto out; + } else if (rc == 0) { + break; // Timeout. + } + + s_ssize_t n = send (device->fd, (char*) data + nbytes, size - nbytes, 0); + if (n < 0) { + s_errcode_t errcode = S_ERRNO; + if (errcode == S_EINTR || errcode == S_EAGAIN) + continue; // Retry. + SYSERROR (device->context, errcode); + status = syserror(errcode); + goto out; + } else if (n == 0) { + break; // EOF. } nbytes += n;