Replace select() with poll() to allow waiting on more than FD_SETSIZE fds
This commit is contained in:
parent
25ed842725
commit
c0d940978a
|
@ -33,7 +33,6 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
@ -43,6 +42,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
@ -4789,8 +4789,7 @@ void Worker::waitForInput()
|
||||||
terminated. */
|
terminated. */
|
||||||
|
|
||||||
bool useTimeout = false;
|
bool useTimeout = false;
|
||||||
struct timeval timeout;
|
long timeout = 0;
|
||||||
timeout.tv_usec = 0;
|
|
||||||
auto before = steady_time_point::clock::now();
|
auto before = steady_time_point::clock::now();
|
||||||
|
|
||||||
/* If we're monitoring for silence on stdout/stderr, or if there
|
/* If we're monitoring for silence on stdout/stderr, or if there
|
||||||
|
@ -4808,7 +4807,7 @@ void Worker::waitForInput()
|
||||||
nearest = std::min(nearest, i.timeStarted + std::chrono::seconds(settings.buildTimeout));
|
nearest = std::min(nearest, i.timeStarted + std::chrono::seconds(settings.buildTimeout));
|
||||||
}
|
}
|
||||||
if (nearest != steady_time_point::max()) {
|
if (nearest != steady_time_point::max()) {
|
||||||
timeout.tv_sec = std::max(1L, (long) std::chrono::duration_cast<std::chrono::seconds>(nearest - before).count());
|
timeout = std::max(1L, (long) std::chrono::duration_cast<std::chrono::seconds>(nearest - before).count());
|
||||||
useTimeout = true;
|
useTimeout = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4819,30 +4818,28 @@ void Worker::waitForInput()
|
||||||
if (lastWokenUp == steady_time_point::min())
|
if (lastWokenUp == steady_time_point::min())
|
||||||
printError("waiting for locks or build slots...");
|
printError("waiting for locks or build slots...");
|
||||||
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
|
if (lastWokenUp == steady_time_point::min() || lastWokenUp > before) lastWokenUp = before;
|
||||||
timeout.tv_sec = std::max(1L,
|
timeout = std::max(1L,
|
||||||
(long) std::chrono::duration_cast<std::chrono::seconds>(
|
(long) std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
lastWokenUp + std::chrono::seconds(settings.pollInterval) - before).count());
|
lastWokenUp + std::chrono::seconds(settings.pollInterval) - before).count());
|
||||||
} else lastWokenUp = steady_time_point::min();
|
} else lastWokenUp = steady_time_point::min();
|
||||||
|
|
||||||
if (useTimeout)
|
if (useTimeout)
|
||||||
vomit("sleeping %d seconds", timeout.tv_sec);
|
vomit("sleeping %d seconds", timeout);
|
||||||
|
|
||||||
/* Use select() to wait for the input side of any logger pipe to
|
/* Use select() to wait for the input side of any logger pipe to
|
||||||
become `available'. Note that `available' (i.e., non-blocking)
|
become `available'. Note that `available' (i.e., non-blocking)
|
||||||
includes EOF. */
|
includes EOF. */
|
||||||
fd_set fds;
|
std::vector<struct pollfd> pollStatus;
|
||||||
FD_ZERO(&fds);
|
std::map <int, int> fdToPollStatus;
|
||||||
int fdMax = 0;
|
|
||||||
for (auto & i : children) {
|
for (auto & i : children) {
|
||||||
for (auto & j : i.fds) {
|
for (auto & j : i.fds) {
|
||||||
if (j >= FD_SETSIZE)
|
pollStatus.push_back((struct pollfd) { .fd = j, .events = POLLIN });
|
||||||
throw Error("reached FD_SETSIZE limit");
|
fdToPollStatus[j] = pollStatus.size() - 1;
|
||||||
FD_SET(j, &fds);
|
|
||||||
if (j >= fdMax) fdMax = j + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (select(fdMax, &fds, 0, 0, useTimeout ? &timeout : 0) == -1) {
|
if (poll(pollStatus.data(), pollStatus.size(),
|
||||||
|
useTimeout ? timeout * 1000 : -1) == -1) {
|
||||||
if (errno == EINTR) return;
|
if (errno == EINTR) return;
|
||||||
throw SysError("waiting for input");
|
throw SysError("waiting for input");
|
||||||
}
|
}
|
||||||
|
@ -4863,7 +4860,7 @@ void Worker::waitForInput()
|
||||||
set<int> fds2(j->fds);
|
set<int> fds2(j->fds);
|
||||||
std::vector<unsigned char> buffer(4096);
|
std::vector<unsigned char> buffer(4096);
|
||||||
for (auto & k : fds2) {
|
for (auto & k : fds2) {
|
||||||
if (FD_ISSET(k, &fds)) {
|
if (pollStatus.at(fdToPollStatus.at(k)).revents) {
|
||||||
ssize_t rd = read(k, buffer.data(), buffer.size());
|
ssize_t rd = read(k, buffer.data(), buffer.size());
|
||||||
// FIXME: is there a cleaner way to handle pt close
|
// FIXME: is there a cleaner way to handle pt close
|
||||||
// than EIO? Is this even standard?
|
// than EIO? Is this even standard?
|
||||||
|
|
Loading…
Reference in a new issue