From 9bda455f7e710ba30d5fb98b0c485423a8cc499e Mon Sep 17 00:00:00 2001 From: eidheim Date: Fri, 14 Aug 2020 10:09:29 +0200 Subject: [PATCH] Fixed deadlock in Terminal::process calls where waiting prints would stop a process from exiting --- src/terminal.cpp | 37 +++++++++++++++++++++---------------- src/terminal.hpp | 3 --- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/terminal.cpp b/src/terminal.cpp index 74ee370..2da47f8 100644 --- a/src/terminal.cpp +++ b/src/terminal.cpp @@ -81,9 +81,9 @@ int Terminal::process(const std::string &command, const boost::filesystem::path std::unique_ptr process; if(use_pipes) process = std::make_unique(command, path.string(), [this](const char *bytes, size_t n) { - sync_print(std::string(bytes, n)); + async_print(std::string(bytes, n)); }, [this](const char *bytes, size_t n) { - sync_print(std::string(bytes, n), true); + async_print(std::string(bytes, n), true); }); else process = std::make_unique(command, path.string()); @@ -111,7 +111,7 @@ int Terminal::process(std::istream &stdin_stream, std::ostream &stdout_stream, c if(stderr_stream) stderr_stream->write(bytes, n); else - sync_print(std::string(bytes, n), true); + async_print(std::string(bytes, n), true); }, true); if(process.get_id() <= 0) { @@ -140,11 +140,25 @@ void Terminal::async_process(const std::string &command, const boost::filesystem LockGuard lock(processes_mutex); stdin_buffer.clear(); auto process = std::make_shared(command, path.string(), [this, quiet](const char *bytes, size_t n) { - if(!quiet) - sync_print(std::string(bytes, n)); + if(!quiet) { + // Print stdout message sequentially to avoid the GUI becoming unresponsive + std::promise message_printed; + dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { + Terminal::get().print(std::move(message)); + message_printed.set_value(); + }); + message_printed.get_future().get(); + } }, [this, quiet](const char *bytes, size_t n) { - if(!quiet) - sync_print(std::string(bytes, n), true); + if(!quiet) { + // Print stderr message sequentially to avoid the GUI becoming unresponsive + std::promise message_printed; + dispatcher.post([message = std::string(bytes, n), &message_printed]() mutable { + Terminal::get().print(std::move(message), true); + message_printed.set_value(); + }); + message_printed.get_future().get(); + } }, true); auto pid = process->get_id(); if(pid <= 0) { @@ -328,15 +342,6 @@ void Terminal::async_print(std::string message, bool bold) { }); } -void Terminal::sync_print(std::string message, bool bold) { - std::promise message_printed; - dispatcher.post([message = std::move(message), bold, &message_printed]() mutable { - Terminal::get().print(std::move(message), bold); - message_printed.set_value(); - }); - message_printed.get_future().get(); -} - void Terminal::configure() { link_tag->property_foreground_rgba() = get_style_context()->get_color(Gtk::StateFlags::STATE_FLAG_LINK); diff --git a/src/terminal.hpp b/src/terminal.hpp index 4c4818e..f130727 100644 --- a/src/terminal.hpp +++ b/src/terminal.hpp @@ -49,9 +49,6 @@ private: Glib::RefPtr default_mouse_cursor; size_t deleted_lines = 0; - /// Made for tiny-process-library handlers: prints in GUI thread, and waits until the message has been printed. Callable from any thread. - void sync_print(std::string message, bool bold = false); - struct Link { int start_pos, end_pos; std::string path;