File indexing completed on 2025-01-18 09:50:05
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
0011 #define BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
0012
0013 #include <boost/process/detail/handler_base.hpp>
0014 #include <boost/process/detail/posix/async_handler.hpp>
0015 #include <boost/asio/write.hpp>
0016 #include <boost/process/async_pipe.hpp>
0017 #include <memory>
0018 #include <future>
0019 #include <boost/process/detail/used_handles.hpp>
0020 #include <array>
0021
0022 namespace boost { namespace process { namespace detail { namespace posix {
0023
0024
0025 template<typename Buffer>
0026 struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
0027 ::boost::process::detail::posix::require_io_context,
0028 ::boost::process::detail::uses_handles
0029 {
0030 Buffer & buf;
0031
0032 std::shared_ptr<std::promise<void>> promise;
0033 async_in_buffer operator>(std::future<void> & fut)
0034 {
0035 promise = std::make_shared<std::promise<void>>();
0036 fut = promise->get_future(); return std::move(*this);
0037 }
0038
0039
0040 std::shared_ptr<boost::process::async_pipe> pipe;
0041
0042 async_in_buffer(Buffer & buf) : buf(buf)
0043 {
0044 }
0045 template <typename Executor>
0046 inline void on_success(Executor)
0047 {
0048 auto pipe_ = this->pipe;
0049 if (this->promise)
0050 {
0051 auto promise_ = this->promise;
0052
0053 boost::asio::async_write(*pipe_, buf,
0054 [pipe_, promise_](const boost::system::error_code & ec, std::size_t)
0055 {
0056 if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
0057 {
0058 std::error_code e(ec.value(), std::system_category());
0059 promise_->set_exception(std::make_exception_ptr(process_error(e)));
0060 }
0061 else
0062 promise_->set_value();
0063 });
0064 }
0065 else
0066 boost::asio::async_write(*pipe_, buf,
0067 [pipe_](const boost::system::error_code&, std::size_t){});
0068
0069 std::move(*pipe_).source().close();
0070
0071 this->pipe = nullptr;
0072 }
0073
0074 template<typename Executor>
0075 void on_error(Executor &, const std::error_code &) const
0076 {
0077 std::move(*pipe).source().close();
0078 }
0079
0080 template<typename Executor>
0081 void on_setup(Executor & exec)
0082 {
0083 if (!pipe)
0084 pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq));
0085 }
0086
0087 std::array<int, 3> get_used_handles()
0088 {
0089 if (pipe)
0090 return {STDIN_FILENO, pipe->native_source(), pipe->native_sink()};
0091 else
0092 return {STDIN_FILENO, STDIN_FILENO, STDIN_FILENO};
0093 }
0094
0095
0096 template <typename Executor>
0097 void on_exec_setup(Executor &exec)
0098 {
0099 if (::dup2(pipe->native_source(), STDIN_FILENO) == -1)
0100 exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
0101
0102 if (pipe->native_source() != STDIN_FILENO)
0103 ::close(pipe->native_source());
0104 ::close(pipe->native_sink());
0105 }
0106 };
0107
0108
0109 }}}}
0110
0111 #endif