Skip to content

Instantly share code, notes, and snippets.

@adventurist
Created August 18, 2020 01:14
Show Gist options
  • Save adventurist/dbd080359024d7eea70c225ec1a98563 to your computer and use it in GitHub Desktop.
Save adventurist/dbd080359024d7eea70c225ec1a98563 to your computer and use it in GitHub Desktop.
poll forked process
struct ProcessResult {
std::string output;
bool error = false;
};
ProcessResult run(std::vector<std::string> args) {
int stdout_fds[2], stderr_fds[2];
pipe(stdout_fds);
pipe(stderr_fds);
const pid_t pid = fork();
if (!pid) { // Child process
close(stdout_fds[0]);
dup2 (stdout_fds[1], 1);
close(stdout_fds[1]);
close(stderr_fds[0]);
dup2 (stderr_fds[1], 2);
close(stderr_fds[1]);
std::vector<char*> process_arguments{};
process_arguments.reserve(args.size() + 1);
for (size_t i = 0; i < args.size(); ++i) {
process_arguments[i] = const_cast<char*>(args[i].c_str());
}
// Execute
execvp(process_arguments[0], &process_arguments[0]);
exit(0); // Exit with no error
}
close(stdout_fds[1]);
close(stderr_fds[1]);
ProcessResult result{}; // To gather result
pollfd poll_fds[2]{
pollfd{
.fd = stdout_fds[0] & 0xFF,
.events = POLL_IN,
.revents = short{0}
},
pollfd{
.fd = stderr_fds[0] & 0xFF,
.events = POLLIN,
.revents = short{0}
}
};
for (;;) {
poll(poll_fds, 2, 30000);
// stdout
if (poll_fds[0].revents & POLLIN) {
result.output = readFd(poll_fds[0].fd);
if (!result.output.empty()) {
break;
}
result.error = true;
poll_fds[0].revents = 0;
}
if (poll_fds[0].revents & POLLHUP) {
close(stdout_fds[0]);
close(stderr_fds[0]);
printf("POLLHUP\n");
result.output = "Lost connection to forked process";
result.error = true;
break;
}
// stderr
if (poll_fds[1].revents & POLL_IN) {
std::string stderr_output = readFd(poll_fds[0].fd);
result.output = stderr_output;
result.error = true;
break;
}
}
close(stdout_fds[0]);
close(stderr_fds[0]);
std::cout << "Result output: " << result.output << std::endl;
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment