From b0ddbfc2dfc7de25d3cbda1d39be7da564a1ddac Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sat, 4 Nov 2023 17:23:09 +0100 Subject: [PATCH] Do not poll command sockets while shell command is running Accepter is a wrapper around a socket watcher. It always uses EventMode::Urgent, so it will be included in pselect(2) (via EventManager::handle_next_events()) even while we are waiting for a (blocking) shell command. However we will not execute the command received on this socket until after the shell command is done. This is implemented with an early return: void handle_available_input(EventMode mode) { while (not m_reader.ready() and fd_readable(sock)) m_reader.read_available(sock); if (mode != EventMode::Normal or not m_reader.ready()) return; so we read available data but don't close the socket. When using this reproducer { sleep 1 && echo 'nop' | kak -p session } & kak -n -s session -e '%sh{sleep 7}' the first "m_reader.read_available(sock);" will read "nop". Then "m_reader.ready()" is true but the socket is still readable. This means that pselect(2) will return it every time, without blocking. This means that the shell manager runs a hot loop between pselect(2) and waitpid(2). Fix this problem demoting command socket watchers from EventMode::Urgent. This means that we won't pselect(2) it when handling only urgent events. Control-C still works, I'm not sure why. Alternative fix: we could read the commands but then disable the socket. I tried this but it seems too complex. Closes #5014 --- src/remote.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote.cc b/src/remote.cc index 5b97f985..025a4458 100644 --- a/src/remote.cc +++ b/src/remote.cc @@ -776,7 +776,7 @@ class Server::Accepter { public: Accepter(int socket) - : m_socket_watcher(socket, FdEvents::Read, EventMode::Urgent, + : m_socket_watcher(socket, FdEvents::Read, EventMode::Normal, [this](FDWatcher&, FdEvents, EventMode mode) { handle_available_input(mode); })