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
{
FifoWatcher(int fd, Buffer& buffer, bool scroll)
: FDWatcher(fd, FdEvents::Read,
: FDWatcher(fd, FdEvents::Read, EventMode::Normal,
[](FDWatcher& watcher, FdEvents, EventMode mode) {
if (mode == EventMode::Normal)
static_cast<FifoWatcher&>(watcher).read_fifo();

View File

@ -12,8 +12,8 @@
namespace Kakoune
{
FDWatcher::FDWatcher(int fd, FdEvents events, Callback callback)
: m_fd{fd}, m_events{events}, m_callback{std::move(callback)}
FDWatcher::FDWatcher(int fd, FdEvents events, EventMode mode, Callback callback)
: m_fd{fd}, m_events{events}, m_mode{mode}, m_callback{std::move(callback)}
{
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);
for (auto& watcher : m_fd_watchers)
{
if (watcher->mode() == EventMode::Normal and mode == EventMode::Urgent)
continue;
const int fd = watcher->fd();
if (fd != -1)
{

View File

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

View File

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

View File

@ -327,7 +327,7 @@ static void signal_handler(int)
NCursesUI::NCursesUI()
: m_cursor{CursorMode::Buffer, {}},
m_stdin_watcher{STDIN_FILENO, FdEvents::Read,
m_stdin_watcher{STDIN_FILENO, FdEvents::Read, EventMode::Urgent,
[this](FDWatcher&, FdEvents, EventMode) {
if (not m_on_key)
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)
: m_socket_watcher(socket, FdEvents::Read | FdEvents::Write,
: m_socket_watcher(socket, FdEvents::Read | FdEvents::Write, EventMode::Urgent,
[this](FDWatcher& watcher, FdEvents events, EventMode) {
const int sock = watcher.fd();
try
@ -663,7 +663,7 @@ RemoteClient::RemoteClient(StringView session, StringView name, std::unique_ptr<
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 {
const int sock = watcher.fd();
if (events & FdEvents::Write and send_data(sock, m_send_buffer))
@ -777,7 +777,7 @@ class Server::Accepter
{
public:
Accepter(int socket)
: m_socket_watcher(socket, FdEvents::Read,
: m_socket_watcher(socket, FdEvents::Read, EventMode::Urgent,
[this](FDWatcher&, FdEvents, EventMode 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_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)

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)
{
return {pipe.read_fd(), FdEvents::Read,
return {pipe.read_fd(), FdEvents::Read, EventMode::Urgent,
[&contents, &pipe](FDWatcher& watcher, FdEvents, EventMode) {
char buffer[1024];
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);
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 {
while (fd_writable(pipe.write_fd()))
{