mirror of
https://github.com/NixOS/nix
synced 2025-07-03 14:31:46 +02:00
Merge pull request #12687 from Mic92/handle-eagain
libutil/file-descriptor: handle EAGAIN in read/write operations
This commit is contained in:
commit
12ad06c104
1 changed files with 40 additions and 4 deletions
|
@ -5,9 +5,27 @@
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// This function is needed to handle non-blocking reads/writes. This is needed in the buildhook, because
|
||||||
|
// somehow the json logger file descriptor ends up beeing non-blocking and breaks remote-building.
|
||||||
|
// TODO: get rid of buildhook and remove this function again (https://github.com/NixOS/nix/issues/12688)
|
||||||
|
void pollFD(int fd, int events)
|
||||||
|
{
|
||||||
|
struct pollfd pfd;
|
||||||
|
pfd.fd = fd;
|
||||||
|
pfd.events = events;
|
||||||
|
int ret = poll(&pfd, 1, -1);
|
||||||
|
if (ret == -1) {
|
||||||
|
throw SysError("poll on file descriptor failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string readFile(int fd)
|
std::string readFile(int fd)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -17,14 +35,18 @@ std::string readFile(int fd)
|
||||||
return drainFD(fd, true, st.st_size);
|
return drainFD(fd, true, st.st_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void readFull(int fd, char * buf, size_t count)
|
void readFull(int fd, char * buf, size_t count)
|
||||||
{
|
{
|
||||||
while (count) {
|
while (count) {
|
||||||
checkInterrupt();
|
checkInterrupt();
|
||||||
ssize_t res = read(fd, buf, count);
|
ssize_t res = read(fd, buf, count);
|
||||||
if (res == -1) {
|
if (res == -1) {
|
||||||
if (errno == EINTR) continue;
|
switch (errno) {
|
||||||
|
case EINTR: continue;
|
||||||
|
case EAGAIN:
|
||||||
|
pollFD(fd, POLLIN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
throw SysError("reading from file");
|
throw SysError("reading from file");
|
||||||
}
|
}
|
||||||
if (res == 0) throw EndOfFile("unexpected end-of-file");
|
if (res == 0) throw EndOfFile("unexpected end-of-file");
|
||||||
|
@ -39,8 +61,15 @@ void writeFull(int fd, std::string_view s, bool allowInterrupts)
|
||||||
while (!s.empty()) {
|
while (!s.empty()) {
|
||||||
if (allowInterrupts) checkInterrupt();
|
if (allowInterrupts) checkInterrupt();
|
||||||
ssize_t res = write(fd, s.data(), s.size());
|
ssize_t res = write(fd, s.data(), s.size());
|
||||||
if (res == -1 && errno != EINTR)
|
if (res == -1) {
|
||||||
|
switch (errno) {
|
||||||
|
case EINTR: continue;
|
||||||
|
case EAGAIN:
|
||||||
|
pollFD(fd, POLLOUT);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
throw SysError("writing to file");
|
throw SysError("writing to file");
|
||||||
|
}
|
||||||
if (res > 0)
|
if (res > 0)
|
||||||
s.remove_prefix(res);
|
s.remove_prefix(res);
|
||||||
}
|
}
|
||||||
|
@ -56,8 +85,15 @@ std::string readLine(int fd, bool eofOk)
|
||||||
// FIXME: inefficient
|
// FIXME: inefficient
|
||||||
ssize_t rd = read(fd, &ch, 1);
|
ssize_t rd = read(fd, &ch, 1);
|
||||||
if (rd == -1) {
|
if (rd == -1) {
|
||||||
if (errno != EINTR)
|
switch (errno) {
|
||||||
|
case EINTR: continue;
|
||||||
|
case EAGAIN: {
|
||||||
|
pollFD(fd, POLLIN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
default:
|
||||||
throw SysError("reading a line");
|
throw SysError("reading a line");
|
||||||
|
}
|
||||||
} else if (rd == 0) {
|
} else if (rd == 0) {
|
||||||
if (eofOk)
|
if (eofOk)
|
||||||
return s;
|
return s;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue