diff --git a/CHANGES b/CHANGES index df3ae2b..f1efbcc 100644 --- a/CHANGES +++ b/CHANGES @@ -20,6 +20,8 @@ Corrections: Do not log simple successful write with NOTICE level. + On partial write to not poll with sleep() but use select()/poll(). + Building: Disabling certain features during configure could break build process. diff --git a/sysutils.c b/sysutils.c index 777388f..a581a53 100644 --- a/sysutils.c +++ b/sysutils.c @@ -35,6 +35,9 @@ const int one = 1; ssize_t writefull(int fd, const void *buff, size_t bytes) { size_t writt = 0; ssize_t chk; + struct pollfd pfd; + int rc; + while (1) { chk = Write(fd, (const char *)buff + writt, bytes - writt); if (chk < 0) { @@ -45,10 +48,22 @@ ssize_t writefull(int fd, const void *buff, size_t bytes) { case EWOULDBLOCK: #endif Warn4("write(%d, %p, "F_Zu"): %s", fd, (const char *)buff+writt, bytes-writt, strerror(errno)); - Sleep(1); + pfd.fd = fd; + pfd.events = POLLOUT; + pfd.revents = 0; + rc = xiopoll(&pfd, 1, NULL); + if (rc == 0) { + Notice("inactivity timeout triggered"); + errno = ETIMEDOUT; + return -1; + } continue; - default: return -1; + default: + return -1; } + } else if (chk == bytes) { + /* First attempt, complete write */ + return chk; } else if (writt+chk < bytes) { Warn4("write(%d, %p, "F_Zu"): only wrote "F_Zu" bytes, trying to continue (meanwhile, other direction is blocked)", fd, (const char *)buff+writt, bytes-writt, chk); @@ -56,6 +71,8 @@ ssize_t writefull(int fd, const void *buff, size_t bytes) { } else if (writt == 0) { /* First attempt, write complete - no extra message */ return chk; + } else { /* write completed */ + break; } } Notice3("write(%d, %p, "F_Zu") completed", fd, (const char *)buff, bytes);