Do not select on non-urgent fd when handling only urgent events

This avoids 100% CPU usage when we have pending fifo input while running
a shell process, as we will not end-up busy looping in pselect but not
reading the available data due to being only processing urgent events.
This commit is contained in:
Maxime Coste 2021-03-11 09:02:02 +11:00
parent c12d1c16b7
commit 4a59018dcd
7 changed files with 17 additions and 12 deletions

View File

@ -133,7 +133,7 @@ Buffer* create_fifo_buffer(String name, int fd, Buffer::Flags flags, bool scroll
struct FifoWatcher : FDWatcher struct FifoWatcher : FDWatcher
{ {
FifoWatcher(int fd, Buffer& buffer, bool scroll) FifoWatcher(int fd, Buffer& buffer, bool scroll)
: FDWatcher(fd, FdEvents::Read, : FDWatcher(fd, FdEvents::Read, EventMode::Normal,
[](FDWatcher& watcher, FdEvents, EventMode mode) { [](FDWatcher& watcher, FdEvents, EventMode mode) {
if (mode == EventMode::Normal) if (mode == EventMode::Normal)
static_cast<FifoWatcher&>(watcher).read_fifo(); static_cast<FifoWatcher&>(watcher).read_fifo();

View File

@ -12,8 +12,8 @@
namespace Kakoune namespace Kakoune
{ {
FDWatcher::FDWatcher(int fd, FdEvents events, Callback callback) FDWatcher::FDWatcher(int fd, FdEvents events, EventMode mode, Callback callback)
: m_fd{fd}, m_events{events}, m_callback{std::move(callback)} : m_fd{fd}, m_events{events}, m_mode{mode}, m_callback{std::move(callback)}
{ {
EventManager::instance().m_fd_watchers.push_back(this); EventManager::instance().m_fd_watchers.push_back(this);
} }
@ -80,6 +80,9 @@ bool EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, bool bl
FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds); FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
for (auto& watcher : m_fd_watchers) for (auto& watcher : m_fd_watchers)
{ {
if (watcher->mode() == EventMode::Normal and mode == EventMode::Urgent)
continue;
const int fd = watcher->fd(); const int fd = watcher->fd();
if (fd != -1) if (fd != -1)
{ {

View File

@ -34,7 +34,7 @@ class FDWatcher
{ {
public: public:
using Callback = std::function<void (FDWatcher& watcher, FdEvents events, EventMode mode)>; using Callback = std::function<void (FDWatcher& watcher, FdEvents events, EventMode mode)>;
FDWatcher(int fd, FdEvents events, Callback callback); FDWatcher(int fd, FdEvents events, EventMode mode, Callback callback);
FDWatcher(const FDWatcher&) = delete; FDWatcher(const FDWatcher&) = delete;
FDWatcher& operator=(const FDWatcher&) = delete; FDWatcher& operator=(const FDWatcher&) = delete;
~FDWatcher(); ~FDWatcher();
@ -42,6 +42,7 @@ public:
int fd() const { return m_fd; } int fd() const { return m_fd; }
FdEvents events() const { return m_events; } FdEvents events() const { return m_events; }
FdEvents& events() { return m_events; } FdEvents& events() { return m_events; }
EventMode mode() const { return m_mode; }
void run(FdEvents events, EventMode mode); void run(FdEvents events, EventMode mode);
@ -51,6 +52,7 @@ public:
private: private:
int m_fd; int m_fd;
FdEvents m_events; FdEvents m_events;
EventMode m_mode;
Callback m_callback; Callback m_callback;
}; };

View File

@ -133,7 +133,7 @@ void rpc_call(StringView method, Args&&... args)
} }
JsonUI::JsonUI() JsonUI::JsonUI()
: m_stdin_watcher{0, FdEvents::Read, : m_stdin_watcher{0, FdEvents::Read, EventMode::Urgent,
[this](FDWatcher&, FdEvents, EventMode mode) { [this](FDWatcher&, FdEvents, EventMode mode) {
parse_requests(mode); parse_requests(mode);
}}, m_dimensions{24, 80} }}, m_dimensions{24, 80}

View File

@ -327,7 +327,7 @@ static void signal_handler(int)
NCursesUI::NCursesUI() NCursesUI::NCursesUI()
: m_cursor{CursorMode::Buffer, {}}, : m_cursor{CursorMode::Buffer, {}},
m_stdin_watcher{STDIN_FILENO, FdEvents::Read, m_stdin_watcher{STDIN_FILENO, FdEvents::Read, EventMode::Urgent,
[this](FDWatcher&, FdEvents, EventMode) { [this](FDWatcher&, FdEvents, EventMode) {
if (not m_on_key) if (not m_on_key)
return; return;

View File

@ -461,7 +461,7 @@ static bool send_data(int fd, RemoteBuffer& buffer, Optional<int> ancillary_fd =
} }
RemoteUI::RemoteUI(int socket, DisplayCoord dimensions) RemoteUI::RemoteUI(int socket, DisplayCoord dimensions)
: m_socket_watcher(socket, FdEvents::Read | FdEvents::Write, : m_socket_watcher(socket, FdEvents::Read | FdEvents::Write, EventMode::Urgent,
[this](FDWatcher& watcher, FdEvents events, EventMode) { [this](FDWatcher& watcher, FdEvents events, EventMode) {
const int sock = watcher.fd(); const int sock = watcher.fd();
try try
@ -663,7 +663,7 @@ RemoteClient::RemoteClient(StringView session, StringView name, std::unique_ptr<
m_socket_watcher->events() |= FdEvents::Write; m_socket_watcher->events() |= FdEvents::Write;
}); });
m_socket_watcher.reset(new FDWatcher{sock, FdEvents::Read | FdEvents::Write, m_socket_watcher.reset(new FDWatcher{sock, FdEvents::Read | FdEvents::Write, EventMode::Urgent,
[this, reader = MsgReader{}](FDWatcher& watcher, FdEvents events, EventMode) mutable { [this, reader = MsgReader{}](FDWatcher& watcher, FdEvents events, EventMode) mutable {
const int sock = watcher.fd(); const int sock = watcher.fd();
if (events & FdEvents::Write and send_data(sock, m_send_buffer)) if (events & FdEvents::Write and send_data(sock, m_send_buffer))
@ -777,7 +777,7 @@ class Server::Accepter
{ {
public: public:
Accepter(int socket) Accepter(int socket)
: m_socket_watcher(socket, FdEvents::Read, : m_socket_watcher(socket, FdEvents::Read, EventMode::Urgent,
[this](FDWatcher&, FdEvents, EventMode mode) { [this](FDWatcher&, FdEvents, EventMode mode) {
handle_available_input(mode); handle_available_input(mode);
}) })
@ -888,7 +888,7 @@ Server::Server(String session_name, bool is_daemon)
m_accepters.emplace_back(new Accepter{sock}); m_accepters.emplace_back(new Accepter{sock});
}; };
m_listener.reset(new FDWatcher{listen_sock, FdEvents::Read, accepter}); m_listener.reset(new FDWatcher{listen_sock, FdEvents::Read, EventMode::Urgent, accepter});
} }
bool Server::rename_session(StringView name) bool Server::rename_session(StringView name)

View File

@ -167,7 +167,7 @@ Vector<String> generate_env(StringView cmdline, const Context& context, const Sh
FDWatcher make_pipe_reader(Pipe& pipe, String& contents) FDWatcher make_pipe_reader(Pipe& pipe, String& contents)
{ {
return {pipe.read_fd(), FdEvents::Read, return {pipe.read_fd(), FdEvents::Read, EventMode::Urgent,
[&contents, &pipe](FDWatcher& watcher, FdEvents, EventMode) { [&contents, &pipe](FDWatcher& watcher, FdEvents, EventMode) {
char buffer[1024]; char buffer[1024];
while (fd_readable(pipe.read_fd())) while (fd_readable(pipe.read_fd()))
@ -188,7 +188,7 @@ FDWatcher make_pipe_writer(Pipe& pipe, StringView contents)
{ {
int flags = fcntl(pipe.write_fd(), F_GETFL, 0); int flags = fcntl(pipe.write_fd(), F_GETFL, 0);
fcntl(pipe.write_fd(), F_SETFL, flags | O_NONBLOCK); fcntl(pipe.write_fd(), F_SETFL, flags | O_NONBLOCK);
return {pipe.write_fd(), FdEvents::Write, return {pipe.write_fd(), FdEvents::Write, EventMode::Urgent,
[contents, &pipe](FDWatcher& watcher, FdEvents, EventMode) mutable { [contents, &pipe](FDWatcher& watcher, FdEvents, EventMode) mutable {
while (fd_writable(pipe.write_fd())) while (fd_writable(pipe.write_fd()))
{ {