From 897f87e76ac051b50b8438d2355463b95f6cd805 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Thu, 3 Jul 2025 22:37:40 +0200 Subject: [PATCH] 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 --- lix/libutil/file-descriptor.cc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/lix/libutil/file-descriptor.cc b/lix/libutil/file-descriptor.cc index 7edec8f49..5a2658406 100644 --- a/lix/libutil/file-descriptor.cc +++ b/lix/libutil/file-descriptor.cc @@ -6,7 +6,9 @@ #include "lix/libutil/serialise.hh" #include "lix/libutil/signals.hh" +#include #include +#include #include #include @@ -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); }