Fixed 2 issues:

1. When more than 2 streams are piped, we use threads to read/write data
parallely. In this scenariod read_atmost_n API was being used instead of
read_all.
2. Another issue with check_output argument validation fixed.
This commit is contained in:
arunmu 2016-03-21 20:25:37 +05:30
parent a67cb2a439
commit a23c1033df
5 changed files with 23 additions and 15 deletions

View File

@ -1245,11 +1245,12 @@ namespace detail {
} }
void ArgumentDeducer::set_option(error&& err) { void ArgumentDeducer::set_option(error&& err) {
if (err.deferred_ && popen_->stream_.write_to_parent_) { if (err.deferred_) {
if (popen_->stream_.write_to_parent_) {
popen_->stream_.err_write_ = popen_->stream_.write_to_parent_; popen_->stream_.err_write_ = popen_->stream_.write_to_parent_;
return;
} else { } else {
throw "Set output before redirecting error to output"; throw std::runtime_error("Set output before redirecting error to output");
}
} }
if (err.wr_ch_ != -1) popen_->stream_.err_write_ = err.wr_ch_; if (err.wr_ch_ != -1) popen_->stream_.err_write_ = err.wr_ch_;
if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_; if (err.rd_ch_ != -1) popen_->stream_.err_read_ = err.rd_ch_;
@ -1466,26 +1467,23 @@ namespace detail {
{ {
OutBuffer obuf; OutBuffer obuf;
ErrBuffer ebuf; ErrBuffer ebuf;
std::future<int> out_fut, err_fut; std::future<int> out_fut, err_fut;
if (stream_->output()) { if (stream_->output()) {
obuf.add_cap(out_buf_cap_); obuf.add_cap(out_buf_cap_);
out_fut = std::async(std::launch::async, out_fut = std::async(std::launch::async,
util::read_atmost_n, [&obuf, this] {
fileno(stream_->output()), return util::read_all(fileno(this->stream_->output()), obuf.buf);
obuf.buf.data(), });
obuf.buf.size());
} }
if (stream_->error()) { if (stream_->error()) {
ebuf.add_cap(err_buf_cap_); ebuf.add_cap(err_buf_cap_);
err_fut = std::async(std::launch::async, err_fut = std::async(std::launch::async,
util::read_atmost_n, [&ebuf, this] {
fileno(stream_->error()), return util::read_all(fileno(this->stream_->error()), ebuf.buf);
ebuf.buf.data(), });
ebuf.buf.size());
} }
if (stream_->input()) { if (stream_->input()) {
if (msg) { if (msg) {
@ -1527,7 +1525,7 @@ namespace detail
{ {
static_assert(!detail::has_type<output, detail::param_pack<Args...>>::value, "output not allowed in args"); static_assert(!detail::has_type<output, detail::param_pack<Args...>>::value, "output not allowed in args");
auto p = Popen(std::forward<F>(farg), std::forward<Args>(args)..., output{PIPE}); auto p = Popen(std::forward<F>(farg), std::forward<Args>(args)..., output{PIPE});
auto res = p.communicate(nullptr, 0); auto res = p.communicate();
auto retcode = p.poll(); auto retcode = p.poll();
if (retcode > 0) { if (retcode > 0) {
throw CalledProcessError("Command failed : Non zero retcode"); throw CalledProcessError("Command failed : Non zero retcode");

Binary file not shown.

View File

@ -30,9 +30,19 @@ void test_buffer_growth()
assert (obuf.length > sp::DEFAULT_BUF_CAP_BYTES); assert (obuf.length > sp::DEFAULT_BUF_CAP_BYTES);
} }
void test_buffer_growth_threaded_comm()
{
std::cout << "Test::test_buffer_growth_threaded_comm" << std::endl;
auto buf = sp::check_output("cat ../subprocess.hpp", sp::error{sp::PIPE});
std::cout << buf.length << std::endl;
assert (buf.length > sp::DEFAULT_BUF_CAP_BYTES);
std::cout << "END_TEST" << std::endl;
}
int main() { int main() {
test_cat_pipe_redirection(); test_cat_pipe_redirection();
test_cat_file_redirection(); test_cat_file_redirection();
test_buffer_growth(); test_buffer_growth();
test_buffer_growth_threaded_comm();
return 0; return 0;
} }

Binary file not shown.

Binary file not shown.