From 409d804ee85074eed8bd94f616bc23284bdf5eb9 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 8 Jun 2015 22:42:51 +0100 Subject: [PATCH] Do not close stderr/stdout before program finish Programs like grep called in '$' command will fail due to SIGPIPE for example. So we need to keep the pipe open. --- src/command_manager.cc | 2 +- src/commands.cc | 2 +- src/event_manager.cc | 7 +++++-- src/normal.cc | 4 ++-- src/shell_manager.cc | 16 +++++++--------- src/shell_manager.hh | 4 ++-- 6 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index e57ab196..9ac3a8d4 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -271,7 +271,7 @@ String expand_token(const Token& token, const Context& context, { case Token::Type::ShellExpand: return ShellManager::instance().eval(content, context, {}, - ShellManager::Flags::ReadOutput, + ShellManager::Flags::WaitForStdout, shell_params, env_vars).first; case Token::Type::RegisterExpand: return context.main_sel_register_value(content).str(); diff --git a/src/commands.cc b/src/commands.cc index 6d6a55fc..e73b61ec 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -787,7 +787,7 @@ void define_command(const ParametersParser& parser, Context& context) { "pos_in_token", to_string(pos_in_token) } }; String output = ShellManager::instance().eval(shell_cmd, context, {}, - ShellManager::Flags::ReadOutput, + ShellManager::Flags::WaitForStdout, params, vars).first; return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) }; }; diff --git a/src/event_manager.cc b/src/event_manager.cc index 21cd6331..0b345fc2 100644 --- a/src/event_manager.cc +++ b/src/event_manager.cc @@ -25,8 +25,11 @@ void FDWatcher::run(EventMode mode) void FDWatcher::close_fd() { - close(m_fd); - m_fd = -1; + if (m_fd != -1) + { + close(m_fd); + m_fd = -1; + } } Timer::Timer(TimePoint date, Callback callback, EventMode mode) diff --git a/src/normal.cc b/src/normal.cc index 75fb2b20..8cd44a7b 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -396,7 +396,7 @@ void pipe(Context& context, NormalParams) str += '\n'; str = ShellManager::instance().eval( real_cmd, context, str, - ShellManager::Flags::ReadOutput, + ShellManager::Flags::WaitForStdout, {}, EnvVarMap{}).first; if ((insert_eol or sel.max() == buffer.back_coord()) and @@ -441,7 +441,7 @@ void insert_output(Context& context, NormalParams) return; auto str = ShellManager::instance().eval(real_cmd, context, {}, - ShellManager::Flags::ReadOutput, + ShellManager::Flags::WaitForStdout, {}, EnvVarMap{}).first; ScopedEdition edition(context); context.selections().insert(str, mode); diff --git a/src/shell_manager.cc b/src/shell_manager.cc index ff483d89..3a64eef2 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -60,20 +60,18 @@ std::pair ShellManager::eval( FDWatcher stdout_watcher{read_pipe[0], pipe_reader(child_stdout)}; FDWatcher stderr_watcher{error_pipe[0], pipe_reader(child_stderr)}; - if (not (flags & Flags::ReadOutput)) - { - stdout_watcher.close_fd(); - stderr_watcher.close_fd(); - } - - while (not stdout_watcher.closed() or - not stderr_watcher.closed() or - not terminated) + while (not terminated or + ((flags & Flags::WaitForStdout) and + (not stdout_watcher.closed() or + not stderr_watcher.closed()))) { EventManager::instance().handle_next_events(EventMode::Urgent); if (not terminated) terminated = waitpid(pid, &status, WNOHANG); } + + stdout_watcher.close_fd(); + stderr_watcher.close_fd(); } if (not child_stderr.empty()) diff --git a/src/shell_manager.hh b/src/shell_manager.hh index 36c74a3a..586cf59b 100644 --- a/src/shell_manager.hh +++ b/src/shell_manager.hh @@ -24,12 +24,12 @@ public: enum class Flags { None = 0, - ReadOutput = 1 + WaitForStdout = 1 }; std::pair eval(StringView cmdline, const Context& context, StringView input = {}, - Flags flags = Flags::ReadOutput, + Flags flags = Flags::WaitForStdout, ConstArrayView params = {}, const EnvVarMap& env_vars = EnvVarMap{});