boost :: process redirect stdin, stdout, stderr

Я прошу прощения за длину кода, размещенного здесь. Я пытаюсь создать класс, который использует boost :: process, чтобы порождать процесс, передавать ему некоторые данные на его стандартный вывод и захватывать все его стандартный вывод & STDERR.

Stdin подпроцесса может быть длинным, как и stdout; Целевая машина не имеет большого количества памяти, поэтому каждый из них должен обрабатываться порциями.

Я прочитал бесконечные примеры использования boost :: process, но не нашел ничего, что ответило бы на все эти вопросы вместе. Я попытался объединить эти примеры без успеха. Я явно что-то упускаю. Буду благодарен за любую помощь.

То, что происходит, — то, что дочерний процесс успешно порожден, но ничего не происходит. Остановка родительского процесса в строке, помеченной THUS *.

Класс определен:

class CommandProcessor {
public:
explicit CommandProcessor(const std::string &executable_path, bool slow) :
executable_path_(executable_path), slow_(slow), in_(io_service_, ::dup(STDIN_FILENO)), out_(io_service_, ::dup(STDOUT_FILENO)), err_(io_service_, ::dup(STDERR_FILENO)) {
}

private:
void begin_write_stdin();
void end_write_stdin(const boost::system::error_code &ec, std::size_t bytes_transferred);
void begin_read_stdout();
void end_read_stdout(const boost::system::error_code &ec, std::size_t bytes_transferred);
void begin_read_stderr();
void end_read_stderr(const boost::system::error_code &ec, std::size_t bytes_transferred);

public:
void execute_command(const Command& command);

private:
boost::filesystem::path executable_path_;bool slow_;
boost::asio::io_service io_service_;
boost::asio::posix::stream_descriptor in_;
boost::asio::posix::stream_descriptor out_;
boost::asio::posix::stream_descriptor err_;
std::string stdout_;
std::string stderr_;
std::string stdin_buffer_;
std::array<char, 4096> stdout_buffer_;
std::array<char, 4096> stderr_buffer_;
std::vector<std::string>::const_iterator stdin_it_;
std::vector<std::string>::const_iterator stdin_end_;
};

Код (для краткости я включаю только те биты, которые доставляют мне неприятности):

void CommandProcessor::begin_write_stdin() {
if (stdin_buffer_.size() == 0) {
for (; stdin_it_ != stdin_end_; stdin_it_++) {
if (stdin_buffer_.size() + stdin_it_->size() > 4096) {
break;
}
stdin_buffer_ += *stdin_it_;
}
}
if (stdin_buffer_.size() == 0) {
return;
}
in_.async_write_some(boost::asio::buffer(stdin_buffer_),
boost::bind(&CommandProcessor::end_write_stdin, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void CommandProcessor::end_write_stdin(const boost::system::error_code &ec, std::size_t bytes_transferred __attribute__((unused))) {
if (!ec) {
stdin_it_++;
if (stdin_it_ != stdin_end_) {
begin_write_stdin();
}
}
in_.close();
}

void CommandProcessor::begin_read_stdout() {
out_.async_read_some(boost::asio::buffer(stdout_buffer_),
boost::bind(&CommandProcessor::end_read_stdout, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void CommandProcessor::end_read_stdout(const boost::system::error_code &ec, std::size_t bytes_transferred __attribute__((unused))) {
if (!ec) {
stdout_ += stdout_buffer_.data();
begin_read_stdout();
}
out_.close();
}

void CommandProcessor::begin_read_stderr() {
err_.async_read_some(boost::asio::buffer(stderr_buffer_), boost::bind(&CommandProcessor::end_read_stderr, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
}

void CommandProcessor::end_read_stderr(const boost::system::error_code &ec, std::size_t bytes_transferred __attribute__((unused))) {
if (!ec) {
stderr_ += stderr_buffer_.data();
begin_read_stderr();
}
err_.close();
}void CommandProcessor::execute_command(const Command& command) {
boost::process::context ctx;
ctx.stdin_behavior = boost::process::capture_stream();
ctx.stdout_behavior = boost::process::capture_stream();
ctx.stderr_behavior = boost::process::capture_stream();

stdin_it_ = command.for_stdin_.begin();
stdin_end_ = command.for_stdin_.end();

boost::process::child child(boost::process::launch((executable_path_ / command.executable_name_).string(), command.executable_name_ + command.arguments_, ctx));

boost::process::pistream &child_stdout(child.get_stdout());
**** Halts in next statement
in_.assign(child_stdout.handle().release());
boost::process::pistream &child_stderr(child.get_stderr());
err_.assign(child_stderr.handle().release());
boost::process::postream &child_stdin = child.get_stdin();
out_.assign(child_stdin.handle().release());

begin_read_stdout();
begin_read_stderr();
begin_write_stdin();

boost::process::status child_status(child.wait());
if (child_status.exited()) {
if (child_status.exit_status() == 0) {
throw ProcessorException((boost::format("Exec status %d on %s") % child_status.exit_status() % (executable_path_ / command.executable_name_).string()).str());
}
} else {
throw ProcessorException((boost::format("Exec failure on %s") % (executable_path_ / command.executable_name_).string()).str());
}
}

3

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]