1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-10 12:36:01 +01:00
nix/subprojects/libutil/unix/muxable-pipe.cc
John Ericson 84e2963f8e Move /src to /subprojects
This will facilitate breaking up Nix into multiple packages for each
component with Meson.
2024-10-09 17:38:55 -04:00

47 lines
1.5 KiB
C++

#include <poll.h>
#include "logging.hh"
#include "util.hh"
#include "muxable-pipe.hh"
namespace nix {
void MuxablePipePollState::poll(std::optional<unsigned int> timeout)
{
if (::poll(pollStatus.data(), pollStatus.size(), timeout ? *timeout : -1) == -1) {
if (errno == EINTR)
return;
throw SysError("waiting for input");
}
}
void MuxablePipePollState::iterate(
std::set<MuxablePipePollState::CommChannel> & channels,
std::function<void(Descriptor fd, std::string_view data)> handleRead,
std::function<void(Descriptor fd)> handleEOF)
{
std::set<Descriptor> fds2(channels);
std::vector<unsigned char> buffer(4096);
for (auto & k : fds2) {
const auto fdPollStatusId = get(fdToPollStatus, k);
assert(fdPollStatusId);
assert(*fdPollStatusId < pollStatus.size());
if (pollStatus.at(*fdPollStatusId).revents) {
ssize_t rd = ::read(fromDescriptorReadOnly(k), buffer.data(), buffer.size());
// FIXME: is there a cleaner way to handle pt close
// than EIO? Is this even standard?
if (rd == 0 || (rd == -1 && errno == EIO)) {
handleEOF(k);
channels.erase(k);
} else if (rd == -1) {
if (errno != EINTR)
throw SysError("read failed");
} else {
std::string_view data((char *) buffer.data(), rd);
handleRead(k, data);
}
}
}
}
}