From b2509614e207b458cae23270fa32b40a507f8a78 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Sun, 26 Oct 2014 08:20:39 -0600 Subject: [PATCH] fd write: accomodate non-partial writes to a non-full descriptor If a write to a non-blocking descriptor fails, then try again with fewer bytes, since nothing in the spec write() seems to promise writing partial amounts. In particular, writing to a FIFO no Mac OS X might fail even if there are a few bytes of space; as it happens, the select() function seems to compensate and claim that such a FIFO is full, but kqeueue() doesn't. --- racket/src/racket/src/port.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/racket/src/racket/src/port.c b/racket/src/racket/src/port.c index abda20e15d..a2c5dedb41 100644 --- a/racket/src/racket/src/port.c +++ b/racket/src/racket/src/port.c @@ -8122,13 +8122,23 @@ static intptr_t flush_fd(Scheme_Output_Port *op, } #else int flags; + intptr_t amt; flags = fcntl(fop->fd, F_GETFL, 0); fcntl(fop->fd, F_SETFL, flags | MZ_NONBLOCKING); + amt = buflen - offset; + do { - len = write(fop->fd, bufstr + offset, buflen - offset); - } while ((len == -1) && (errno == EINTR)); + do { + len = write(fop->fd, bufstr + offset, amt); + } while ((len == -1) && (errno == EINTR)); + + /* If there was no room to write `amt` bytes, then it's + possible that writing fewer bytes will succeed. That seems + to be the case with FIFOs on Mac OS X, for example. */ + amt = amt >> 1; + } while ((len == -1) && (errno == EAGAIN) && (amt > 0)); errsaved = errno; fcntl(fop->fd, F_SETFL, flags);