summaryrefslogtreecommitdiff
path: root/src/shell_manager.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2021-11-02 21:50:37 +1100
committerMaxime Coste <mawww@kakoune.org>2021-11-02 21:50:37 +1100
commit19e2225153ce988674ea838989158251f1602789 (patch)
treea08daafb01439a123d6f68bf53237e622f9b0beb /src/shell_manager.cc
parente7adb01316be7da3aaeaa9765c69108e2af3c9f5 (diff)
Keep command_fifo read fd open instead of closing/reopening
Closing/reopening the read side seems to sometimes lead to end-of-file not being received, leaving some extra data unexecuted. The FDWatcher stays disabled during the executing of the fifo commands so this should not enable any more commands to be executed until we get back from the CommandManager and reset the FDWatcher fd to to fifo read end. Fixes #4410
Diffstat (limited to 'src/shell_manager.cc')
-rw-r--r--src/shell_manager.cc19
1 files changed, 12 insertions, 7 deletions
diff --git a/src/shell_manager.cc b/src/shell_manager.cc
index bd101633..ac0eb43b 100644
--- a/src/shell_manager.cc
+++ b/src/shell_manager.cc
@@ -172,7 +172,8 @@ template<typename OnClose>
FDWatcher make_reader(int fd, String& contents, OnClose&& on_close)
{
return {fd, FdEvents::Read, EventMode::Urgent,
- [fd, &contents, on_close](FDWatcher& watcher, FdEvents, EventMode) {
+ [&contents, on_close](FDWatcher& watcher, FdEvents, EventMode) {
+ const int fd = watcher.fd();
char buffer[1024];
while (fd_readable(fd))
{
@@ -183,7 +184,7 @@ FDWatcher make_reader(int fd, String& contents, OnClose&& on_close)
continue; // try again
watcher.disable();
- on_close();
+ on_close(size == 0);
return;
}
contents += StringView{buffer, buffer+size};
@@ -228,11 +229,15 @@ struct CommandFifos
mkfifo(command_fifo_path().c_str(), 0600);
mkfifo(response_fifo_path().c_str(), 0600);
int fd = open(command_fifo_path().c_str(), O_RDONLY | O_NONBLOCK);
- return make_reader(fd, command, [&, fd] {
- close(fd);
+ return make_reader(fd, command, [&, fd](bool graceful) {
+ if (not graceful)
+ {
+ write_to_debug_buffer(format("error reading from command fifo '{}'", strerror(errno)));
+ return;
+ }
CommandManager::instance().execute(command, context, shell_context);
command.clear();
- command_watcher.reset_fd(open(command_fifo_path().c_str(), O_RDONLY | O_NONBLOCK));
+ command_watcher.reset_fd(fd);
});
}())
{
@@ -313,8 +318,8 @@ std::pair<String, int> ShellManager::eval(
auto wait_time = Clock::now();
String stdout_contents, stderr_contents;
- auto stdout_reader = make_reader(child_stdout.read_fd(), stdout_contents, [&]{ child_stdout.close_read_fd(); });
- auto stderr_reader = make_reader(child_stderr.read_fd(), stderr_contents, [&]{ child_stderr.close_read_fd(); });
+ auto stdout_reader = make_reader(child_stdout.read_fd(), stdout_contents, [&](bool){ child_stdout.close_read_fd(); });
+ auto stderr_reader = make_reader(child_stderr.read_fd(), stderr_contents, [&](bool){ child_stderr.close_read_fd(); });
auto stdin_writer = make_pipe_writer(child_stdin, input);
// block SIGCHLD to make sure we wont receive it before