i am trying to write and read to child's stdio using boost.process using something like this:
boost::asio::io_service writeService, readService;
bp::async_pipe in{writeService};
bp::async_pipe out{readService};
bp::child process(CompressCmd.c_str(), bp::std_in < in, bp::std_out > out);
Buffer src;
src.reserve(4 * 1024 * 1024);
integer_type read = 0;
//std::atomic_int64_t totalWrite{0};
integer_type totalWrite = 0;
while (callback(CallbackActions::NeedMoreInput, src, read)) {
in.async_write_some(
boost::asio::buffer(src.data(), read),
[](const boost::system::error_code &e, std::size_t) { });
// written data is not important, that's why using same buffer
out.async_read_some(boost::asio::buffer(src.data(), src.capacity()),
[&](const boost::system::error_code &e,
std::size_t byte_transferred) { totalWrite += byte_transferred; });
}
writeService.run();
in.close();
readService.run();
all read and write operations are noitified as success but value of totalWrite is totally incorrect f.e reported 29356032, real value should be around 50000000
i noticed the program is terminating half way ,
using process.wait() after readService.run() freezes child,
using atomic int produces same behaviour
for now i actually only need to know how much data is actually wriiten, that's why i am using same buffer
This pattern:
is most likely misguided (async operations always immediately return, so you'd simply keep adding more async operations without giving them a chance to run).
Also misguided is the fact that you have separate services for the pipes, but you're running them in total exclusion, so no read operation will ever run until the writeService completes.
atomic
types are misguided since there's no access from multiple threadsWhat are you trying to do? You reserve a large buffer but never put any data into it (
reserve
!=resize
). Therefore you can only hope to write nothing.Even more ironically, you are reading into the exact same buffer, at the exact same spot. However, that's immediately Undefined Behaviour¹ because you pass it
src.capacity()
when you know thatsrc.size()==0
.Even without that error how can you "simultaneously" read and write from exactly the same bytes in memory and still know what the expected outcome would be?
you are not passing your own
io_service
to Boost ProcessA Working Demo
Here's a working sample. Of course I had to guess what you actually want to do.
I opted to make the program send its own source (main.cpp) to stdin, and read stdout iteratively, recording the
total_received
bytes. It then prints the exit code and that total.As a make-shift compressor I used
'/usr/bin/xxd'
because it's available and could even be usefully printed tostd::cout
for debugging.Live On Coliru // trouble on Coliru
Printing
Explanations, Simplifications
Note that we do all of the writing without a loop. That's because
boost::asio::async_write
is a composed operation (it hides the loop).Likewise, if you can "afford" to store the whole received data in memory, you can simplify by using
boost::asio::streambuf
and using a similar composed operation:Live On Coliru // trouble on Coliru
Two Asynchronous Loops, With Delays
Let's do that, and make it more entertaining by delaying a second before writing each block. What you'd expect to see is alternating reads/writes happening because of the delays:
Live On Coliru // yay running on Coliru
Prints
¹ perhaps just unspecified, I'm not inclined to find out the difference right now