summaryrefslogtreecommitdiff
path: root/src/shell_manager.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2021-06-27 16:33:34 +1000
committerMaxime Coste <mawww@kakoune.org>2021-07-07 19:25:06 +1000
commit5ed9e1b356799006fecacb3734e4025a034fde60 (patch)
tree01b770fc6b0abfd9699a2aefee13f728acd0fa1d /src/shell_manager.cc
parent2b68b6737c6b010836637e3fe57bda66a12555ad (diff)
Catch errors while executing shell commands
Log error to debug buffer and Change the 'waiting for shell' face to 'Error'. Update the 'waiting for shell' message when the shell has exited but Kakoune is still waiting on stdin/stdout/stderr to be closed.
Diffstat (limited to 'src/shell_manager.cc')
-rw-r--r--src/shell_manager.cc43
1 files changed, 26 insertions, 17 deletions
diff --git a/src/shell_manager.cc b/src/shell_manager.cc
index 298412b7..e53d4d5c 100644
--- a/src/shell_manager.cc
+++ b/src/shell_manager.cc
@@ -321,34 +321,43 @@ std::pair<String, int> ShellManager::eval(
int status = 0;
// check for termination now that SIGCHLD is blocked
bool terminated = waitpid(pid, &status, WNOHANG) != 0;
+ bool failed = false;
using namespace std::chrono;
static constexpr seconds wait_timeout{1};
Optional<DisplayLine> previous_status;
- Timer wait_timer{wait_time + wait_timeout, [&](Timer& timer)
- {
- auto wait_duration = Clock::now() - wait_time;
- if (context.has_client())
- {
- auto& client = context.client();
- if (not previous_status)
- previous_status = client.current_status();
-
- client.print_status({ format("waiting for shell command to finish ({}s)",
- duration_cast<seconds>(wait_duration).count()),
- context.faces()["Information"] });
- client.redraw_ifn();
- }
- timer.set_next_date(Clock::now() + wait_timeout);
+ Timer wait_timer{wait_time + wait_timeout, [&](Timer& timer) {
+ if (not context.has_client())
+ return;
+
+ const auto now = Clock::now();
+ timer.set_next_date(now + wait_timeout);
+ auto& client = context.client();
+ if (not previous_status)
+ previous_status = client.current_status();
+
+ client.print_status({format("waiting for shell command to finish{} ({}s)",
+ terminated ? " (shell terminated)" : "",
+ duration_cast<seconds>(now - wait_time).count()),
+ context.faces()[failed ? "Error" : "Information"]});
+ client.redraw_ifn();
}, EventMode::Urgent};
while (not terminated or child_stdin.write_fd() != -1 or
((flags & Flags::WaitForStdout) and
(child_stdout.read_fd() != -1 or child_stderr.read_fd() != -1)))
{
- EventManager::instance().handle_next_events(EventMode::Urgent, &orig_mask);
+ try
+ {
+ EventManager::instance().handle_next_events(EventMode::Urgent, &orig_mask);
+ }
+ catch (runtime_error& error)
+ {
+ write_to_debug_buffer(format("error while waiting for shell: {}", error.what()));
+ failed = true;
+ }
if (not terminated)
- terminated = waitpid(pid, &status, WNOHANG) != 0;
+ terminated = waitpid(pid, &status, WNOHANG) == pid;
}
if (not stderr_contents.empty())