[Boost-bugs] [Boost C++ Libraries] #13103: Documentation: Line-by-line I/O example should use asio

Subject: [Boost-bugs] [Boost C++ Libraries] #13103: Documentation: Line-by-line I/O example should use asio
From: Boost C++ Libraries (noreply_at_[hidden])
Date: 2017-06-30 08:50:18


#13103: Documentation: Line-by-line I/O example should use asio
------------------------------+---------------------
 Reporter: joshua.hopp@… | Owner:
     Type: Bugs | Status: new
Milestone: To Be Determined | Component: process
  Version: Boost 1.64.0 | Severity: Problem
 Keywords: |
------------------------------+---------------------
 The boost::process Tutorial needs some improvements:

 When following the example
 "[http://www.boost.org/doc/libs/1_64_0/doc/html/boost_process/tutorial.html#boost_process.tutorial.io
 Synchronous I/O]" the output may be incomplete. Actually, this is even
 stated in the
 [http://www.boost.org/doc/libs/1_64_0/doc/html/boost_process/faq.html#boost_process.faq.closep
 FAQ]: "But, since pipes are buffered, you might get incomplete data if you
 do this: It is therefore highly recommended that you use the asynchronous
 api if you are not absolutely sure how the output will look."

 Not retrieving all data is not something to be generally expected;
 therefore this should be stated clearly in the tutorial's example. A new
 example should provide a solution to the problem. (Would have saved me
 hours of work!)

 Or even better, since the asynchronous api is highly recommended anyway,
 why not deprecate synchronous IO and replace the example completely?

 The new/additional example could look somewhat like this:

 {{{
 #include <boost/process.hpp>
 #include <iostream>
 #include <functional>
 #include <sstream>

 // capture process output line by line
 int main() {
         const std::string file = "file";

         namespace bp = boost::process;

         bp::opstream os;

         struct IoData {
                 bp::async_pipe ap; // Pipe to be used by the stream
                 std::vector<char> buffer;
                 std::mutex streamMutex;
                 std::string keepline; // Store incomplete data
                 std::function<void(const std::string&)> callback;

                 IoData(boost::asio::io_service& ios_,
 std::function<void(const std::string&)> callback_)
                 : ap(ios_)
                 , buffer(512) // Set arbitrary buffer size here!
                 , callback(callback_) {
                 }
         };

         // set up async io
         boost::asio::io_service ios;

         // Prepare capturing both stdout and stderr
         IoData err(ios, [](const std::string& s){ std::cout << "cerr: " <<
 s <<std::endl; });
         IoData out(ios, [](const std::string& s){ std::cout << "cout: " <<
 s <<std::endl; });

         bp::child process(bp::search_path("nm"), file, bp::std_out >
 out.ap, bp::std_err > err.ap, ios);

         std::function<void(IoData&)> beginRead = [&](IoData& io) {
                 io.ap.async_read_some(boost::asio::buffer(io.buffer,
 io.buffer.size()), [&](const boost::system::error_code &ec, std::size_t
 size) {
                                 std::lock_guard<std::mutex>
 guard(io.streamMutex);
                                 std::string str(io.buffer.data(), size);

                                 std::stringstream stream(io.keepline +
 str);
                                 std::string line;
                                 while (std::getline(stream, line)) {
                                         io.callback(line);
                                 }
                                 if (stream.eof()) {
                                         io.keepline = line;
                                 } else {
                                         io.keepline = "";
                                 }

                                 if (ec.value() != 0) {
                                         return;
                                 }

                                 beginRead(io);
                 });
         };

         beginRead(err);
         beginRead(out);
         ios.run();

         process.wait();

 };
 }}}

--
Ticket URL: <https://svn.boost.org/trac10/boost/ticket/13103>
Boost C++ Libraries <http://www.boost.org/>
Boost provides free peer-reviewed portable C++ source libraries.

This archive was generated by hypermail 2.1.7 : 2017-06-30 08:53:11 UTC