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.
This commit is contained in:
parent
6cb7e20d54
commit
409d804ee8
|
@ -271,7 +271,7 @@ String expand_token(const Token& token, const Context& context,
|
||||||
{
|
{
|
||||||
case Token::Type::ShellExpand:
|
case Token::Type::ShellExpand:
|
||||||
return ShellManager::instance().eval(content, context, {},
|
return ShellManager::instance().eval(content, context, {},
|
||||||
ShellManager::Flags::ReadOutput,
|
ShellManager::Flags::WaitForStdout,
|
||||||
shell_params, env_vars).first;
|
shell_params, env_vars).first;
|
||||||
case Token::Type::RegisterExpand:
|
case Token::Type::RegisterExpand:
|
||||||
return context.main_sel_register_value(content).str();
|
return context.main_sel_register_value(content).str();
|
||||||
|
|
|
@ -787,7 +787,7 @@ void define_command(const ParametersParser& parser, Context& context)
|
||||||
{ "pos_in_token", to_string(pos_in_token) }
|
{ "pos_in_token", to_string(pos_in_token) }
|
||||||
};
|
};
|
||||||
String output = ShellManager::instance().eval(shell_cmd, context, {},
|
String output = ShellManager::instance().eval(shell_cmd, context, {},
|
||||||
ShellManager::Flags::ReadOutput,
|
ShellManager::Flags::WaitForStdout,
|
||||||
params, vars).first;
|
params, vars).first;
|
||||||
return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) };
|
return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) };
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,8 +25,11 @@ void FDWatcher::run(EventMode mode)
|
||||||
|
|
||||||
void FDWatcher::close_fd()
|
void FDWatcher::close_fd()
|
||||||
{
|
{
|
||||||
|
if (m_fd != -1)
|
||||||
|
{
|
||||||
close(m_fd);
|
close(m_fd);
|
||||||
m_fd = -1;
|
m_fd = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer::Timer(TimePoint date, Callback callback, EventMode mode)
|
Timer::Timer(TimePoint date, Callback callback, EventMode mode)
|
||||||
|
|
|
@ -396,7 +396,7 @@ void pipe(Context& context, NormalParams)
|
||||||
str += '\n';
|
str += '\n';
|
||||||
str = ShellManager::instance().eval(
|
str = ShellManager::instance().eval(
|
||||||
real_cmd, context, str,
|
real_cmd, context, str,
|
||||||
ShellManager::Flags::ReadOutput,
|
ShellManager::Flags::WaitForStdout,
|
||||||
{}, EnvVarMap{}).first;
|
{}, EnvVarMap{}).first;
|
||||||
|
|
||||||
if ((insert_eol or sel.max() == buffer.back_coord()) and
|
if ((insert_eol or sel.max() == buffer.back_coord()) and
|
||||||
|
@ -441,7 +441,7 @@ void insert_output(Context& context, NormalParams)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto str = ShellManager::instance().eval(real_cmd, context, {},
|
auto str = ShellManager::instance().eval(real_cmd, context, {},
|
||||||
ShellManager::Flags::ReadOutput,
|
ShellManager::Flags::WaitForStdout,
|
||||||
{}, EnvVarMap{}).first;
|
{}, EnvVarMap{}).first;
|
||||||
ScopedEdition edition(context);
|
ScopedEdition edition(context);
|
||||||
context.selections().insert(str, mode);
|
context.selections().insert(str, mode);
|
||||||
|
|
|
@ -60,20 +60,18 @@ std::pair<String, int> ShellManager::eval(
|
||||||
FDWatcher stdout_watcher{read_pipe[0], pipe_reader(child_stdout)};
|
FDWatcher stdout_watcher{read_pipe[0], pipe_reader(child_stdout)};
|
||||||
FDWatcher stderr_watcher{error_pipe[0], pipe_reader(child_stderr)};
|
FDWatcher stderr_watcher{error_pipe[0], pipe_reader(child_stderr)};
|
||||||
|
|
||||||
if (not (flags & Flags::ReadOutput))
|
while (not terminated or
|
||||||
{
|
((flags & Flags::WaitForStdout) and
|
||||||
stdout_watcher.close_fd();
|
(not stdout_watcher.closed() or
|
||||||
stderr_watcher.close_fd();
|
not stderr_watcher.closed())))
|
||||||
}
|
|
||||||
|
|
||||||
while (not stdout_watcher.closed() or
|
|
||||||
not stderr_watcher.closed() or
|
|
||||||
not terminated)
|
|
||||||
{
|
{
|
||||||
EventManager::instance().handle_next_events(EventMode::Urgent);
|
EventManager::instance().handle_next_events(EventMode::Urgent);
|
||||||
if (not terminated)
|
if (not terminated)
|
||||||
terminated = waitpid(pid, &status, WNOHANG);
|
terminated = waitpid(pid, &status, WNOHANG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stdout_watcher.close_fd();
|
||||||
|
stderr_watcher.close_fd();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not child_stderr.empty())
|
if (not child_stderr.empty())
|
||||||
|
|
|
@ -24,12 +24,12 @@ public:
|
||||||
enum class Flags
|
enum class Flags
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
ReadOutput = 1
|
WaitForStdout = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
std::pair<String, int> eval(StringView cmdline, const Context& context,
|
std::pair<String, int> eval(StringView cmdline, const Context& context,
|
||||||
StringView input = {},
|
StringView input = {},
|
||||||
Flags flags = Flags::ReadOutput,
|
Flags flags = Flags::WaitForStdout,
|
||||||
ConstArrayView<String> params = {},
|
ConstArrayView<String> params = {},
|
||||||
const EnvVarMap& env_vars = EnvVarMap{});
|
const EnvVarMap& env_vars = EnvVarMap{});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user