From 616a672d52a61719632b33ea1950fd3eb9e6a360 Mon Sep 17 00:00:00 2001 From: Geert Janssens Date: Thu, 11 Feb 2021 15:05:17 +0100 Subject: [PATCH] Rewrite boost::process call to properly capture both stdout and stderr The previous version of the code could only capture one but not both at the same time. --- libgnucash/app-utils/gnc-quotes.cpp | 43 +++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/libgnucash/app-utils/gnc-quotes.cpp b/libgnucash/app-utils/gnc-quotes.cpp index ee341973ec..97b4887ade 100644 --- a/libgnucash/app-utils/gnc-quotes.cpp +++ b/libgnucash/app-utils/gnc-quotes.cpp @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include "gnc-commodity.hpp" #include "gnc-quotes.hpp" @@ -46,6 +49,7 @@ extern "C" { namespace bp = boost::process; namespace bpt = boost::property_tree; +namespace bio = boost::iostreams; static GncQuotes quotes_cached; static bool quotes_initialized = false; @@ -69,24 +73,35 @@ GncQuotes::check (void) auto perl_executable = bp::search_path("perl"); //or get it from somewhere else. auto fq_check = std::string(gnc_path_get_bindir()) + "/gnc-fq-check"; - bp::ipstream out_stream; - bp::ipstream err_stream; - try { - bp::child process (perl_executable, "-w", fq_check, bp::std_out > out_stream, bp::std_err > err_stream); - - std::string stream_line; - while (process.running() && getline (out_stream, stream_line)) - if (m_version.empty()) - std::swap (m_version, stream_line); - else - m_sources.push_back (std::move(stream_line)); - - while (process.running() && getline (err_stream, stream_line)) - m_error_msg.append(stream_line + "\n"); + std::future > output, error; + boost::asio::io_service svc; + bp::child process (perl_executable, "-w", fq_check, bp::std_out > output, bp::std_err > error, svc); + svc.run(); process.wait(); + + { + auto raw = output.get(); + std::vector data; + std::string line; + bio::stream_buffer sb(raw.data(), raw.size()); + std::istream is(&sb); + + while (std::getline(is, line) && !line.empty()) + if (m_version.empty()) + std::swap (m_version, line); + else + m_sources.push_back (std::move(line)); + + raw = error.get(); + bio::stream_buffer eb(raw.data(), raw.size()); + std::istream es(&eb); + + while (std::getline(es, line) && !line.empty()) + m_error_msg.append(std::move(line) + "\n"); + } m_cmd_result = process.exit_code(); } catch (std::exception &e)