libutil: allow non-blocking fds for writeFull

writing to non-blocking fds happens during remote builds due to the way
file descriptions are shared between processes. we can either poll when
writing to non-blocking fds are reset fd flags. polling is just easier.
unfortunately there is no reasonable way to test this that isn't flaky.

fixes #896

Change-Id: I1d8666df57da97199247f0770c547d0180f6ce07
This commit is contained in:
eldritch horrors
2025-07-03 22:37:40 +02:00
parent 61c276e858
commit 897f87e76a
+12 -2
View File
@@ -6,7 +6,9 @@
#include "lix/libutil/serialise.hh"
#include "lix/libutil/signals.hh"
#include <cerrno>
#include <fcntl.h>
#include <sys/poll.h>
#include <sys/syscall.h>
#include <unistd.h>
@@ -71,8 +73,16 @@ void writeFull(int fd, std::string_view s, bool allowInterrupts)
while (!s.empty()) {
if (allowInterrupts) checkInterrupt();
ssize_t res = write(fd, s.data(), s.size());
if (res == -1 && errno != EINTR)
throw SysError("writing to file");
if (res == -1) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
pollfd pfd = {.fd = fd, .events = POLLOUT};
if (poll(&pfd, 1, -1) < 0) {
throw SysError("polling for writing to file");
}
} else if (errno != EINTR) {
throw SysError("writing to file");
}
}
if (res > 0)
s.remove_prefix(res);
}