diff --git a/include/boost/process/io.hpp b/include/boost/process/io.hpp index b2577e53..72cd98ed 100644 --- a/include/boost/process/io.hpp +++ b/include/boost/process/io.hpp @@ -77,26 +77,13 @@ struct std_in_ api::pipe_in operator<(const boost::iostreams::file_descriptor_source &f) const {return api::pipe_in(f);} api::pipe_in operator<(const pipe & p) const {return api::pipe_in(p);} - api::async_in operator=(asio::mutable_buffer & buf) const {return api::async_in(buf);} - api::async_in operator=(asio::const_buffer & buf) const {return api::async_in(buf);} - api::async_in operator=(asio::streambuf & buf) const {return api::async_in(buf);} - - api::async_in operator<(asio::mutable_buffer & buf) const {return api::async_in(buf);} - api::async_in operator<(asio::const_buffer & buf) const {return api::async_in(buf);} - api::async_in operator<(asio::streambuf & buf) const {return api::async_in(buf);} - -// api::async_in_future operator()(const std::string & st, std::future & fut) {return {st, fut};} -// api::async_in_future> operator()(const std::vector & st, std::future & fut) {return {st, fut};} -// -// using string_cb = const std::function; -// using vector_cb = const std::function(bool &)>; -// -// api::async_in_cb operator<(string_cb & cb) const {return cb;} -// api::async_in_cb operator<(vector_cb & cb) const {return cb;} -// -// api::async_in_cb operator=(string_cb & cb) const {return cb;} -// api::async_in_cb operator=(vector_cb & cb) const {return cb;} + api::async_in_buffer operator=(const asio::mutable_buffer & buf) const {return buf;} + api::async_in_buffer operator=(const asio::const_buffer & buf) const {return buf;} + api::async_in_buffer operator=(asio::streambuf & buf) const {return buf;} + api::async_in_buffer operator<(const asio::mutable_buffer & buf) const {return buf;} + api::async_in_buffer operator<(const asio::const_buffer & buf) const {return buf;} + api::async_in_buffer operator<(asio::streambuf & buf) const {return buf;} }; @@ -139,15 +126,6 @@ struct std_out_ api::async_out_buffer operator>(asio::streambuf & os) const {return os ;} - - using string_cb = const std::function; - using vector_cb = const std::function)>; - - api::async_out_cb operator= (string_cb & f) const {return f;} - api::async_out_cb operator= (vector_cb & f) const {return f;} - api::async_out_cb operator> (string_cb & f) const {return f;} - api::async_out_cb operator> (vector_cb & f) const {return f;} - #if defined (BOOST_PROCESS_USE_FUTURE) api::async_out_future operator=(std::future & fut) const; api::async_out_future operator>(std::future & fut) const; @@ -155,8 +133,6 @@ struct std_out_ api::async_out_future> operator>(std::future> & fut) const; #endif - - template std_out; constexpr static std_out_<2> std_err; -/* -inline std::true_type is_initializer (const std_in_ &) {return {};} -inline std::true_type is_initializer (const std_out_<1> &) {return {};} -inline std::true_type is_initializer (const std_out_<2> &) {return {};} -inline std::true_type is_initializer (const std_out_<1,2> &) {return {};} - - -inline std::true_type is_initializer ( const api::close_in &) {return {}; } -inline std::true_type is_initializer ( const api::null_in &) {return {}; } -inline std::true_type is_initializer ( const api::file_in &) {return {}; } -inline std::true_type is_initializer ( const api::pipe_in &) {return {}; } - -template -inline std::true_type is_initializer ( const api::close_out &) {return {}; } -template -inline std::true_type is_initializer ( const api::null_out &) {return {}; } -template -inline std::true_type is_initializer ( const api::file_out &) {return {}; } -template -inline std::true_type is_initializer ( const api::pipe_out &) {return {}; } - -template -inline std::true_type is_initializer ( const api::async_out_buffer &) {return {}; } - -template -inline std::true_type is_initializer ( const api::async_out_cb &) {return {}; } - -template -inline std::true_type is_initializer ( const api::async_out_cb_until &) {return {}; } -*/ - } using boost::asio::buffer; diff --git a/include/boost/process/windows/async_in.hpp b/include/boost/process/windows/async_in.hpp index ce580b7f..e4197572 100644 --- a/include/boost/process/windows/async_in.hpp +++ b/include/boost/process/windows/async_in.hpp @@ -15,23 +15,98 @@ #include #include +#if defined (BOOST_PROCESS_USE_FUTURE) +#include +#endif + +#include + +using namespace std; + namespace boost { namespace process { namespace detail { namespace windows { -struct async_in : public ::boost::process::detail::handler_base + +template +struct async_in_buffer : ::boost::process::detail::windows::async_handler { - //boost::iostreams::file_descriptor_source file; + std::shared_ptr stream_handle; - template - async_in(T&&) {} + Buffer & buf; - template - void on_setup(WindowsExecutor &e) const +#if defined (BOOST_PROCESS_USE_FUTURE) + std::shared_ptr> promise; + async_in_val operator<(std::future & fut) { - //e.startup_info.hStdInput = file.handle(); - //e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_; + promise = std::make_shared>(); + fut = promise->get_future(); return std::move(*this); + } +#endif + + std::shared_ptr pipe = std::make_shared(boost::process::pipe::create_async()); + //because the pipe will be moved later on, but i might need the source at another point. + boost::iostreams::file_descriptor_source source = pipe->source(); + + async_in_buffer(Buffer & buf) : buf(buf) + { + } + template + inline void on_success(Executor &exec) const + { + boost::asio::io_service &is_ser = get_io_service(exec.seq); + auto stream_handle = this->stream_handle; + auto pipe = this->pipe; + +#if defined (BOOST_PROCESS_USE_FUTURE) + if (this->promise) + { + auto promise = this->promise; + + boost::asio::async_write(*stream_handle, buf, + [promise](const boost::system::error_code & ec, std::size_t) + { + std::error_code e(ec.value(), std::system_category()); + promise->set_exception(std::make_exception_ptr(std::system_error(e))); + promise->set_value(); + }); + } + else +#endif + boost::asio::async_write(*stream_handle, buf, + [stream_handle, pipe](const boost::system::error_code&ec, std::size_t size){}); + } + + template + auto on_exit_handler(Executor & exec) + { + auto stream_handle = this->stream_handle; + auto pipe = this->pipe; + return [stream_handle, pipe](const std::error_code & ec) + { + boost::asio::io_service & ios = stream_handle->get_io_service(); + ios.post([stream_handle] + { + boost::system::error_code ec; + stream_handle->close(ec); + }); + }; + + }; + template + void on_setup(WindowsExecutor &exec) + { + stream_handle = std::make_shared(get_io_service(exec.seq), pipe->sink().handle()); + + boost::detail::winapi::SetHandleInformation(source.handle(), + boost::detail::winapi::HANDLE_FLAG_INHERIT_, + boost::detail::winapi::HANDLE_FLAG_INHERIT_); + + exec.startup_info.hStdInput = source.handle(); + exec.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_; + exec.inherit_handles = true; } }; + }}}} #endif diff --git a/include/boost/process/windows/async_out.hpp b/include/boost/process/windows/async_out.hpp index 8516bcbf..331d0754 100644 --- a/include/boost/process/windows/async_out.hpp +++ b/include/boost/process/windows/async_out.hpp @@ -99,81 +99,11 @@ struct async_out_buffer : ::boost::process::detail::windows::async_handler return [stream_handle, pipe](const std::error_code & ec) { boost::asio::io_service & ios = stream_handle->get_io_service(); - ios.post([stream_handle]{stream_handle->close();}); - - }; - - }; - template - void on_setup(WindowsExecutor &exec) - { - stream_handle = std::make_shared(get_io_service(exec.seq), pipe->source().handle()); - apply_out_handles(exec, sink.handle(), std::integral_constant(), std::integral_constant()); - } -}; - -template struct deduce_async_out_cb_type; -template struct deduce_async_out_cb_type> {using type = T;}; - - -struct completion_handler {}; - -template -struct async_out_cb : ::boost::process::detail::windows::async_handler -{ - Callback cb; - - using argument_type = typename deduce_async_out_cb_type::type; - - std::shared_ptr stream_handle; - std::shared_ptr buffer = std::make_shared(); - - std::shared_ptr pipe = std::make_shared(boost::process::pipe::create_async()); - //because the pipe will be moved later on, but i might need the source at another point. - boost::iostreams::file_descriptor_sink sink = pipe->sink(); - - async_out_cb(const Callback & cb) : cb(cb) {} - - template - inline void on_success(Executor &exec) const - { - boost::asio::io_service &is_ser = get_io_service(exec.seq); - auto& stream_handle = this->stream_handle; - auto pipe = this->pipe; - auto buffer = this->buffer; - auto cb = this->cb; - auto func_p = std::make_shared>(); - - *func_p = [stream_handle, pipe, buffer, cb, func_p](const boost::system::error_code&, std::size_t size) - { - if (buffer->size() > 0) - { - std::istream is (buffer.get()); - argument_type arg; - arg.resize(buffer->size()); - is.read(&*arg.begin(), buffer->size()); - cb(std::move(arg)); - } - if (stream_handle->is_open()) - { - return 1024u; - } - else - return 0u; - }; - - boost::asio::async_read(*stream_handle, *buffer, *func_p, [](const boost::system::error_code & , std::size_t){}); - } - - template - auto on_exit_handler(Executor & exec) - { - auto stream_handle = this->stream_handle; - auto & pipe = this->pipe; - return [stream_handle, pipe](const std::error_code & ec) - { - boost::asio::io_service & ios = stream_handle->get_io_service(); - ios.post([stream_handle]{stream_handle->close();}); + ios.post([stream_handle] + { + boost::system::error_code ec; + stream_handle->close(ec); + }); }; @@ -241,7 +171,11 @@ struct async_out_future : ::boost::process::detail::windows::async_handler return [stream_handle, pipe](const std::error_code & ec) { boost::asio::io_service & ios = stream_handle->get_io_service(); - ios.post([stream_handle]{stream_handle->close();}); + ios.post([stream_handle] + { + boost::system::error_code ec; + stream_handle->close(ec); + }); }; diff --git a/include/boost/process/windows/file_in.hpp b/include/boost/process/windows/file_in.hpp index 6974b96b..71047d20 100644 --- a/include/boost/process/windows/file_in.hpp +++ b/include/boost/process/windows/file_in.hpp @@ -27,6 +27,9 @@ struct file_in : public ::boost::process::detail::handler_base template void on_setup(WindowsExecutor &e) const { + boost::detail::winapi::SetHandleInformation(file.handle(), + boost::detail::winapi::HANDLE_FLAG_INHERIT_, + boost::detail::winapi::HANDLE_FLAG_INHERIT_); e.startup_info.hStdInput = file.handle(); e.startup_info.dwFlags |= boost::detail::winapi::STARTF_USESTDHANDLES_; e.inherit_handles = true; diff --git a/test/async.cpp b/test/async.cpp index 79a19db6..f9b5d753 100644 --- a/test/async.cpp +++ b/test/async.cpp @@ -82,28 +82,44 @@ BOOST_AUTO_TEST_CASE(async_out_stream) BOOST_CHECK(boost::algorithm::starts_with(line, "abc")); } -BOOST_AUTO_TEST_CASE(async_out_callback) + + +BOOST_AUTO_TEST_CASE(async_in_stream) { + cout << "async_in_stream" << endl; using boost::unit_test::framework::master_test_suite; boost::asio::io_service io_service; + std::error_code ec; - std::string result; + boost::asio::streambuf buf; + boost::asio::streambuf in_buf; + + std::string st = "test-"; + + std::ostream ostr(&in_buf); + ostr << "-string" << endl ; bp::execute( master_test_suite().argv[1], - "test", "--echo-stdout", "abc", - bp::std_out>[&](const std::string & val){result = val;}, + "test", "--prefix-once", "test", + bp::std_in < in_buf, + bp::std_out > buf, io_service, ec ); BOOST_REQUIRE(!ec); - io_service.run(); - BOOST_CHECK(false); - BOOST_CHECK(boost::algorithm::starts_with(result, "abc")); + + + std::istream istr(&buf); + + std::string line; + std::getline(istr, line); + BOOST_CHECK(boost::algorithm::starts_with(line, "test-string")); } + diff --git a/test/bind_stdin.cpp b/test/bind_stdin.cpp index 50efdf1a..4133ab75 100644 --- a/test/bind_stdin.cpp +++ b/test/bind_stdin.cpp @@ -35,7 +35,6 @@ typedef boost::asio::windows::stream_handle pipe_end; typedef boost::asio::posix::stream_descriptor pipe_end; #endif -#define L() std::cout << __LINE__ << std::endl; namespace bp = boost::process;