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.
This commit is contained in:
Matthew Flatt 2014-10-26 08:20:39 -06:00
parent 5dad9a1ef1
commit b2509614e2

View File

@ -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);