std::pair<IOBufQueue, IOBufQueue> Subprocess::communicateIOBuf( IOBufQueue input) { // If the user supplied a non-empty input buffer, make sure // that stdin is a pipe so we can write the data. if (!input.empty()) { // findByChildFd() will throw std::invalid_argument if no pipe for // STDIN_FILENO exists findByChildFd(STDIN_FILENO); } std::pair<IOBufQueue, IOBufQueue> out; auto readCallback = [&] (int pfd, int cfd) -> bool { if (cfd == STDOUT_FILENO) { return handleRead(pfd, out.first); } else if (cfd == STDERR_FILENO) { return handleRead(pfd, out.second); } else { // Don't close the file descriptor, the child might not like SIGPIPE, // just read and throw the data away. return discardRead(pfd); } }; auto writeCallback = [&] (int pfd, int cfd) -> bool { if (cfd == STDIN_FILENO) { return handleWrite(pfd, input); } else { // If we don't want to write to this fd, just close it. return true; } }; communicate(std::move(readCallback), std::move(writeCallback)); return out; }
void Subprocess::closeParentFd(int childFd) { int idx = findByChildFd(childFd); closeChecked(pipes_[idx].parentFd); pipes_.erase(pipes_.begin() + idx); }
bool Subprocess::notificationsEnabled(int childFd) const { return pipes_[findByChildFd(childFd)].enabled; }
void Subprocess::enableNotifications(int childFd, bool enabled) { pipes_[findByChildFd(childFd)].enabled = enabled; }
void Subprocess::closeParentFd(int childFd) { int idx = findByChildFd(childFd); pipes_[idx].pipe.close(); // May throw pipes_.erase(pipes_.begin() + idx); }