mirror of
https://github.com/hyprwm/hyprutils.git
synced 2024-11-17 07:15:58 +01:00
process: better reading for spawnSync
This commit is contained in:
parent
8d21d1dfa9
commit
4c5f18d06b
1 changed files with 53 additions and 18 deletions
|
@ -10,6 +10,7 @@ using namespace Hyprutils::OS;
|
||||||
|
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
#include <sys/poll.h>
|
||||||
|
|
||||||
Hyprutils::OS::CProcess::CProcess(const std::string& binary_, const std::vector<std::string>& args_) : binary(binary_), args(args_) {
|
Hyprutils::OS::CProcess::CProcess(const std::string& binary_, const std::vector<std::string>& args_) : binary(binary_), args(args_) {
|
||||||
;
|
;
|
||||||
|
@ -75,35 +76,69 @@ bool Hyprutils::OS::CProcess::runSync() {
|
||||||
if (fcntl(errPipe[0], F_SETFL, fdFlags | O_NONBLOCK) < 0)
|
if (fcntl(errPipe[0], F_SETFL, fdFlags | O_NONBLOCK) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// FIXME: this sucks, but it prevents a pipe deadlock.
|
pollfd pollfds[2] = {
|
||||||
// Problem is, if we exceed the 64k buffer, we end up in a deadlock.
|
{
|
||||||
// So, as a "solution", we keep reading until the child pid exits.
|
.fd = outPipe[0],
|
||||||
// If nothing is read from either stdout or stderr, sleep for 100µs, to maybe not peg a core THAT much.
|
.events = POLLIN,
|
||||||
// If anyone knows a better solution, feel free to make a MR.
|
},
|
||||||
|
{
|
||||||
|
.fd = errPipe[0],
|
||||||
|
.events = POLLIN,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
while (waitpid(pid, nullptr, WNOHANG) == 0) {
|
while (1337) {
|
||||||
int any = 0;
|
int ret = poll(pollfds, 2, 5000);
|
||||||
|
|
||||||
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
if (ret < 0) {
|
||||||
out += std::string{(char*)buf.data(), (size_t)ret};
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
any += errno == EWOULDBLOCK || errno == EAGAIN ? 1 : 0;
|
bool hupd = false;
|
||||||
|
|
||||||
buf.fill(0);
|
for (size_t i = 0; i < 2; ++i) {
|
||||||
|
if (pollfds[i].revents & POLLHUP) {
|
||||||
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
hupd = true;
|
||||||
err += std::string{(char*)buf.data(), (size_t)ret};
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
any += errno == EWOULDBLOCK || errno == EAGAIN ? 1 : 0;
|
if (hupd)
|
||||||
|
break;
|
||||||
|
|
||||||
buf.fill(0);
|
if (pollfds[0].revents & POLLIN) {
|
||||||
|
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
||||||
|
out += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
|
}
|
||||||
|
|
||||||
if (any >= 2)
|
buf.fill(0);
|
||||||
std::this_thread::sleep_for(std::chrono::microseconds(100));
|
}
|
||||||
|
|
||||||
|
if (pollfds[1].revents & POLLIN) {
|
||||||
|
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
||||||
|
err += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.fill(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Final reads. Nonblock, so its ok.
|
||||||
|
while ((ret = read(outPipe[0], buf.data(), 1023)) > 0) {
|
||||||
|
out += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.fill(0);
|
||||||
|
|
||||||
|
while ((ret = read(errPipe[0], buf.data(), 1023)) > 0) {
|
||||||
|
err += std::string_view{(char*)buf.data(), (size_t)ret};
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.fill(0);
|
||||||
|
|
||||||
close(outPipe[0]);
|
close(outPipe[0]);
|
||||||
close(errPipe[0]);
|
close(errPipe[0]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue