diff options
Diffstat (limited to 'boost/process/detail/posix')
24 files changed, 1522 insertions, 1430 deletions
diff --git a/boost/process/detail/posix/asio_fwd.hpp b/boost/process/detail/posix/asio_fwd.hpp index 06d5c19214..faa7a9d7a2 100644 --- a/boost/process/detail/posix/asio_fwd.hpp +++ b/boost/process/detail/posix/asio_fwd.hpp @@ -20,34 +20,33 @@ template<typename Allocator> class basic_streambuf; typedef basic_streambuf<std::allocator<char>> streambuf; -class io_service; +class io_context; +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) class signal_set_service; template <typename SignalSetService> class basic_signal_set; typedef basic_signal_set<signal_set_service> signal_set; +#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */ +class signal_set; +#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */ template <typename Handler> class basic_yield_context; namespace posix { +#if defined(BOOST_ASIO_ENABLE_OLD_SERVICES) class stream_descriptor_service; template <typename StreamDesscriptorService> class basic_stream_descriptor; typedef basic_stream_descriptor<stream_descriptor_service> stream_descriptor; - - - -class object_handle_service; - -template <typename ObjectHandleService> -class basic_object_handle; - -typedef basic_object_handle<object_handle_service> object_handle; +#else /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */ +class stream_descriptor; +#endif /* defined(BOOST_ASIO_ENABLE_OLD_SERVICES) */ } //posix } //asio diff --git a/boost/process/detail/posix/async_handler.hpp b/boost/process/detail/posix/async_handler.hpp index a61cff3372..e25860ad69 100644 --- a/boost/process/detail/posix/async_handler.hpp +++ b/boost/process/detail/posix/async_handler.hpp @@ -1,40 +1,40 @@ -// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
-#define BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_
+#ifndef BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_ +#define BOOST_PROCESS_POSIX_ASYNC_HANDLER_HPP_ -#include <boost/process/detail/posix/handler.hpp>
-#include <type_traits>
+#include <boost/process/detail/posix/handler.hpp> +#include <type_traits> -namespace boost { namespace process { namespace detail { namespace posix {
+namespace boost { namespace process { namespace detail { namespace posix { -struct require_io_service {};
+struct require_io_context {}; -struct async_handler : handler_base_ext, require_io_service
-{
-};
+struct async_handler : handler_base_ext, require_io_context +{ +}; -template<typename T>
-struct is_async_handler : std::is_base_of<async_handler, T> {};
-template<typename T>
-struct is_async_handler<T&> : std::is_base_of<async_handler, T> {};
-template<typename T>
-struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {};
+template<typename T> +struct is_async_handler : std::is_base_of<async_handler, T> {}; +template<typename T> +struct is_async_handler<T&> : std::is_base_of<async_handler, T> {}; +template<typename T> +struct is_async_handler<const T&> : std::is_base_of<async_handler, T> {}; -template<typename T>
-struct does_require_io_service : std::is_base_of<require_io_service, T> {};
+template<typename T> +struct does_require_io_context : std::is_base_of<require_io_context, T> {}; -template<typename T>
-struct does_require_io_service<T&> : std::is_base_of<require_io_service, T> {};
+template<typename T> +struct does_require_io_context<T&> : std::is_base_of<require_io_context, T> {}; -template<typename T>
-struct does_require_io_service<const T&> : std::is_base_of<require_io_service, T> {};
+template<typename T> +struct does_require_io_context<const T&> : std::is_base_of<require_io_context, T> {}; -}}}}
+}}}} -#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */
+#endif /* BOOST_PROCESS_WINDOWS_ASYNC_HANDLER_HPP_ */ diff --git a/boost/process/detail/posix/async_in.hpp b/boost/process/detail/posix/async_in.hpp index 9814c593f2..1c1e2f40fb 100644 --- a/boost/process/detail/posix/async_in.hpp +++ b/boost/process/detail/posix/async_in.hpp @@ -1,95 +1,95 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
-#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP
- -#include <boost/process/detail/handler_base.hpp>
-#include <boost/process/detail/posix/async_handler.hpp>
-#include <boost/asio/write.hpp>
-#include <boost/process/async_pipe.hpp>
-#include <memory>
-#include <future>
- -namespace boost { namespace process { namespace detail { namespace posix {
- - -template<typename Buffer>
-struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext,
- ::boost::process::detail::posix::require_io_service
-{
- Buffer & buf;
- - std::shared_ptr<std::promise<void>> promise;
- async_in_buffer operator>(std::future<void> & fut)
- {
- promise = std::make_shared<std::promise<void>>();
- fut = promise->get_future(); return std::move(*this);
- }
- - std::shared_ptr<boost::process::async_pipe> pipe;
- - async_in_buffer(Buffer & buf) : buf(buf)
- {
- }
- template <typename Executor>
- inline void on_success(Executor &exec)
- {
- auto pipe = this->pipe;
- if (this->promise)
- {
- auto promise = this->promise;
- - boost::asio::async_write(*pipe, buf,
- [pipe, promise](const boost::system::error_code & ec, std::size_t)
- {
- if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT))
- {
- std::error_code e(ec.value(), std::system_category());
- promise->set_exception(std::make_exception_ptr(process_error(e)));
- }
- else
- promise->set_value();
- });
- }
- else
- boost::asio::async_write(*pipe, buf,
- [pipe](const boost::system::error_code&ec, std::size_t size){});
- - std::move(*pipe).source().close();
- - this->pipe = nullptr;
- }
- - template<typename Executor>
- void on_error(Executor &, const std::error_code &) const
- {
- std::move(*pipe).source().close();
- }
- - template<typename Executor>
- void on_setup(Executor & exec)
- {
- pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
- }
- - template <typename Executor>
- void on_exec_setup(Executor &exec)
- {
- if (::dup2(pipe->native_source(), STDIN_FILENO) == -1)
- exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- - ::close(pipe->native_source());
- }
-};
- - -}}}}
- -#endif
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP +#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_IN_HPP + +#include <boost/process/detail/handler_base.hpp> +#include <boost/process/detail/posix/async_handler.hpp> +#include <boost/asio/write.hpp> +#include <boost/process/async_pipe.hpp> +#include <memory> +#include <future> + +namespace boost { namespace process { namespace detail { namespace posix { + + +template<typename Buffer> +struct async_in_buffer : ::boost::process::detail::posix::handler_base_ext, + ::boost::process::detail::posix::require_io_context +{ + Buffer & buf; + + std::shared_ptr<std::promise<void>> promise; + async_in_buffer operator>(std::future<void> & fut) + { + promise = std::make_shared<std::promise<void>>(); + fut = promise->get_future(); return std::move(*this); + } + + std::shared_ptr<boost::process::async_pipe> pipe; + + async_in_buffer(Buffer & buf) : buf(buf) + { + } + template <typename Executor> + inline void on_success(Executor &exec) + { + auto pipe = this->pipe; + if (this->promise) + { + auto promise = this->promise; + + boost::asio::async_write(*pipe, buf, + [pipe, promise](const boost::system::error_code & ec, std::size_t) + { + if (ec && (ec.value() != EBADF) && (ec.value() != EPERM) && (ec.value() != ENOENT)) + { + std::error_code e(ec.value(), std::system_category()); + promise->set_exception(std::make_exception_ptr(process_error(e))); + } + else + promise->set_value(); + }); + } + else + boost::asio::async_write(*pipe, buf, + [pipe](const boost::system::error_code&ec, std::size_t size){}); + + std::move(*pipe).source().close(); + + this->pipe = nullptr; + } + + template<typename Executor> + void on_error(Executor &, const std::error_code &) const + { + std::move(*pipe).source().close(); + } + + template<typename Executor> + void on_setup(Executor & exec) + { + pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq)); + } + + template <typename Executor> + void on_exec_setup(Executor &exec) + { + if (::dup2(pipe->native_source(), STDIN_FILENO) == -1) + exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + + ::close(pipe->native_source()); + } +}; + + +}}}} + +#endif diff --git a/boost/process/detail/posix/async_out.hpp b/boost/process/detail/posix/async_out.hpp index b0f7876714..c448490e67 100644 --- a/boost/process/detail/posix/async_out.hpp +++ b/boost/process/detail/posix/async_out.hpp @@ -1,170 +1,170 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
-#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP
- - -#include <boost/process/detail/posix/handler.hpp>
-#include <boost/asio/posix/stream_descriptor.hpp>
-#include <boost/asio/read.hpp>
-#include <boost/process/async_pipe.hpp>
-#include <istream>
-#include <memory>
-#include <exception>
-#include <future>
- -namespace boost { namespace process { namespace detail { namespace posix {
- - -inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>)
-{
- return ::dup2(handle, STDOUT_FILENO);
-}
- -inline int apply_out_handles(int handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>)
-{
- return ::dup2(handle, STDERR_FILENO);
-}
- -inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>)
-{
- if (::dup2(handle, STDOUT_FILENO) == -1)
- return -1;
- if (::dup2(handle, STDERR_FILENO) == -1)
- return -1;
- - return 0;
-}
- -template<int p1, int p2, typename Buffer>
-struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext,
- ::boost::process::detail::posix::require_io_service
-{
- Buffer & buf;
- - std::shared_ptr<boost::process::async_pipe> pipe;
- - - async_out_buffer(Buffer & buf) : buf(buf)
- {
- }
- - template <typename Executor>
- inline void on_success(Executor &exec)
- {
- auto pipe = this->pipe;
- boost::asio::async_read(*pipe, buf,
- [pipe](const boost::system::error_code&, std::size_t size){});
- - this->pipe = nullptr;
- std::move(*pipe).sink().close();
- }
- - template<typename Executor>
- void on_error(Executor &, const std::error_code &) const
- {
- std::move(*pipe).sink().close();
- }
- - template<typename Executor>
- void on_setup(Executor & exec)
- {
- pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
- }
- - - template <typename Executor>
- void on_exec_setup(Executor &exec)
- {
- int res = apply_out_handles(pipe->native_sink(),
- std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
- if (res == -1)
- exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- - ::close(pipe->native_sink());
- }
-};
- - - - -template<int p1, int p2, typename Type>
-struct async_out_future : ::boost::process::detail::posix::handler_base_ext,
- ::boost::process::detail::posix::require_io_service
-{
- std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>();
- - std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>();
- - std::shared_ptr<boost::process::async_pipe> pipe;
- - async_out_future(std::future<Type> & fut)
- {
- fut = promise->get_future();
- }
- template <typename Executor>
- inline void on_success(Executor &exec)
- {
- auto pipe = this->pipe;
- - auto buffer = this->buffer;
- auto promise = this->promise;
- - boost::asio::async_read(*pipe, *buffer,
- [pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size)
- {
- if (ec && (ec.value() != ENOENT))
- {
- std::error_code e(ec.value(), std::system_category());
- promise->set_exception(std::make_exception_ptr(process_error(e)));
- }
- else
- {
- std::istream is (buffer.get());
- Type arg;
- arg.resize(buffer->size());
- is.read(&*arg.begin(), buffer->size());
- promise->set_value(std::move(arg));
- }
- });
- - std::move(*pipe).sink().close();
- this->pipe = nullptr;
- }
- - template<typename Executor>
- void on_error(Executor &, const std::error_code &) const
- {
- std::move(*pipe).sink().close();
- }
- - template<typename Executor>
- void on_setup(Executor & exec)
- {
- pipe = std::make_shared<boost::process::async_pipe>(get_io_service(exec.seq));
- }
- - template <typename Executor>
- void on_exec_setup(Executor &exec)
- {
- - int res = apply_out_handles(pipe->native_sink(),
- std::integral_constant<int, p1>(), std::integral_constant<int, p2>());
- if (res == -1)
- exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- - ::close(pipe->native_sink());
- }
- -};
- -}}}}
- -#endif
+#ifndef BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP +#define BOOST_PROCESS_DETAIL_POSIX_ASYNC_OUT_HPP + + +#include <boost/process/detail/posix/handler.hpp> +#include <boost/asio/posix/stream_descriptor.hpp> +#include <boost/asio/read.hpp> +#include <boost/process/async_pipe.hpp> +#include <istream> +#include <memory> +#include <exception> +#include <future> + +namespace boost { namespace process { namespace detail { namespace posix { + + +inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, -1>) +{ + return ::dup2(handle, STDOUT_FILENO); +} + +inline int apply_out_handles(int handle, std::integral_constant<int, 2>, std::integral_constant<int, -1>) +{ + return ::dup2(handle, STDERR_FILENO); +} + +inline int apply_out_handles(int handle, std::integral_constant<int, 1>, std::integral_constant<int, 2>) +{ + if (::dup2(handle, STDOUT_FILENO) == -1) + return -1; + if (::dup2(handle, STDERR_FILENO) == -1) + return -1; + + return 0; +} + +template<int p1, int p2, typename Buffer> +struct async_out_buffer : ::boost::process::detail::posix::handler_base_ext, + ::boost::process::detail::posix::require_io_context +{ + Buffer & buf; + + std::shared_ptr<boost::process::async_pipe> pipe; + + + async_out_buffer(Buffer & buf) : buf(buf) + { + } + + template <typename Executor> + inline void on_success(Executor &exec) + { + auto pipe = this->pipe; + boost::asio::async_read(*pipe, buf, + [pipe](const boost::system::error_code&, std::size_t size){}); + + this->pipe = nullptr; + std::move(*pipe).sink().close(); + } + + template<typename Executor> + void on_error(Executor &, const std::error_code &) const + { + std::move(*pipe).sink().close(); + } + + template<typename Executor> + void on_setup(Executor & exec) + { + pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq)); + } + + + template <typename Executor> + void on_exec_setup(Executor &exec) + { + int res = apply_out_handles(pipe->native_sink(), + std::integral_constant<int, p1>(), std::integral_constant<int, p2>()); + if (res == -1) + exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + + ::close(pipe->native_sink()); + } +}; + + + + +template<int p1, int p2, typename Type> +struct async_out_future : ::boost::process::detail::posix::handler_base_ext, + ::boost::process::detail::posix::require_io_context +{ + std::shared_ptr<std::promise<Type>> promise = std::make_shared<std::promise<Type>>(); + + std::shared_ptr<boost::asio::streambuf> buffer = std::make_shared<boost::asio::streambuf>(); + + std::shared_ptr<boost::process::async_pipe> pipe; + + async_out_future(std::future<Type> & fut) + { + fut = promise->get_future(); + } + template <typename Executor> + inline void on_success(Executor &exec) + { + auto pipe = this->pipe; + + auto buffer = this->buffer; + auto promise = this->promise; + + boost::asio::async_read(*pipe, *buffer, + [pipe, buffer, promise](const boost::system::error_code& ec, std::size_t size) + { + if (ec && (ec.value() != ENOENT)) + { + std::error_code e(ec.value(), std::system_category()); + promise->set_exception(std::make_exception_ptr(process_error(e))); + } + else + { + std::istream is (buffer.get()); + Type arg; + arg.resize(buffer->size()); + is.read(&*arg.begin(), buffer->size()); + promise->set_value(std::move(arg)); + } + }); + + std::move(*pipe).sink().close(); + this->pipe = nullptr; + } + + template<typename Executor> + void on_error(Executor &, const std::error_code &) const + { + std::move(*pipe).sink().close(); + } + + template<typename Executor> + void on_setup(Executor & exec) + { + pipe = std::make_shared<boost::process::async_pipe>(get_io_context(exec.seq)); + } + + template <typename Executor> + void on_exec_setup(Executor &exec) + { + + int res = apply_out_handles(pipe->native_sink(), + std::integral_constant<int, p1>(), std::integral_constant<int, p2>()); + if (res == -1) + exec.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + + ::close(pipe->native_sink()); + } + +}; + +}}}} + +#endif diff --git a/boost/process/detail/posix/async_pipe.hpp b/boost/process/detail/posix/async_pipe.hpp index d849559c20..8f138bdfa3 100644 --- a/boost/process/detail/posix/async_pipe.hpp +++ b/boost/process/detail/posix/async_pipe.hpp @@ -11,6 +11,7 @@ #include <boost/asio/posix/stream_descriptor.hpp> #include <system_error> #include <string> +#include <utility> namespace boost { namespace process { namespace detail { namespace posix { @@ -22,10 +23,10 @@ public: typedef int native_handle_type; typedef ::boost::asio::posix::stream_descriptor handle_type; - inline async_pipe(boost::asio::io_service & ios) : async_pipe(ios, ios) {} + inline async_pipe(boost::asio::io_context & ios) : async_pipe(ios, ios) {} - inline async_pipe(boost::asio::io_service & ios_source, - boost::asio::io_service & ios_sink) : _source(ios_source), _sink(ios_sink) + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink) : _source(ios_source), _sink(ios_sink) { int fds[2]; if (::pipe(fds) == -1) @@ -34,11 +35,11 @@ public: _source.assign(fds[0]); _sink .assign(fds[1]); }; - inline async_pipe(boost::asio::io_service & ios, const std::string & name) + inline async_pipe(boost::asio::io_context & ios, const std::string & name) : async_pipe(ios, ios, name) {} - inline async_pipe(boost::asio::io_service & ios_source, - boost::asio::io_service & io_sink, const std::string & name); + inline async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & io_sink, const std::string & name); inline async_pipe(const async_pipe& lhs); async_pipe(async_pipe&& lhs) : _source(std::move(lhs._source)), _sink(std::move(lhs._sink)) { @@ -47,15 +48,15 @@ public: } template<class CharT, class Traits = std::char_traits<CharT>> - explicit async_pipe(::boost::asio::io_service & ios_source, - ::boost::asio::io_service & ios_sink, + explicit async_pipe(::boost::asio::io_context & ios_source, + ::boost::asio::io_context & ios_sink, const basic_pipe<CharT, Traits> & p) : _source(ios_source, p.native_source()), _sink(ios_sink, p.native_sink()) { } template<class CharT, class Traits = std::char_traits<CharT>> - explicit async_pipe(boost::asio::io_service & ios, const basic_pipe<CharT, Traits> & p) + explicit async_pipe(boost::asio::io_context & ios, const basic_pipe<CharT, Traits> & p) : async_pipe(ios, ios, p) { } @@ -68,10 +69,10 @@ public: ~async_pipe() { - if (_sink .native() != -1) - ::close(_sink.native()); - if (_source.native() != -1) - ::close(_source.native()); + if (_sink .native_handle() != -1) + ::close(_sink.native_handle()); + if (_source.native_handle() != -1) + ::close(_source.native_handle()); } template<class CharT, class Traits = std::char_traits<CharT>> @@ -108,9 +109,9 @@ public: void async_close() { if (_sink.is_open()) - _sink.get_io_service(). post([this]{_sink.close();}); + _sink.get_io_context(). post([this]{_sink.close();}); if (_source.is_open()) - _source.get_io_service().post([this]{_source.close();}); + _source.get_io_context().post([this]{_source.close();}); } template<typename MutableBufferSequence> @@ -124,8 +125,8 @@ public: return _sink.write_some(buffers); } - native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native();} - native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native();} + native_handle_type native_source() const {return const_cast<boost::asio::posix::stream_descriptor&>(_source).native_handle();} + native_handle_type native_sink () const {return const_cast<boost::asio::posix::stream_descriptor&>(_sink ).native_handle();} template<typename MutableBufferSequence, typename ReadHandler> @@ -156,32 +157,32 @@ public: handle_type && sink() && { return std::move(_sink); } handle_type && source()&& { return std::move(_source); } - handle_type source(::boost::asio::io_service& ios) && + handle_type source(::boost::asio::io_context& ios) && { ::boost::asio::posix::stream_descriptor stolen(ios, _source.release()); return stolen; } - handle_type sink (::boost::asio::io_service& ios) && + handle_type sink (::boost::asio::io_context& ios) && { ::boost::asio::posix::stream_descriptor stolen(ios, _sink.release()); return stolen; } - handle_type source(::boost::asio::io_service& ios) const & + handle_type source(::boost::asio::io_context& ios) const & { - auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native(); + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); return ::boost::asio::posix::stream_descriptor(ios, ::dup(source_in)); } - handle_type sink (::boost::asio::io_service& ios) const & + handle_type sink (::boost::asio::io_context& ios) const & { - auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); return ::boost::asio::posix::stream_descriptor(ios, ::dup(sink_in)); } }; -async_pipe::async_pipe(boost::asio::io_service & ios_source, - boost::asio::io_service & ios_sink, +async_pipe::async_pipe(boost::asio::io_context & ios_source, + boost::asio::io_context & ios_sink, const std::string & name) : _source(ios_source), _sink(ios_sink) { auto fifo = mkfifo(name.c_str(), 0666 ); @@ -205,19 +206,19 @@ async_pipe::async_pipe(boost::asio::io_service & ios_source, } async_pipe::async_pipe(const async_pipe & p) : - _source(const_cast<async_pipe&>(p)._source.get_io_service()), - _sink( const_cast<async_pipe&>(p)._sink.get_io_service()) + _source(const_cast<async_pipe&>(p)._source.get_io_context()), + _sink( const_cast<async_pipe&>(p)._sink.get_io_context()) { //cannot get the handle from a const object. - auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native(); - auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native(); + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); if (source_in == -1) _source.assign(-1); else { _source.assign(::dup(source_in)); - if (_source.native()== -1) + if (_source.native_handle()== -1) ::boost::process::detail::throw_last_error("dup()"); } @@ -226,7 +227,7 @@ async_pipe::async_pipe(const async_pipe & p) : else { _sink.assign(::dup(sink_in)); - if (_sink.native() == -1) + if (_sink.native_handle() == -1) ::boost::process::detail::throw_last_error("dup()"); } } @@ -237,8 +238,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p) int sink; //cannot get the handle from a const object. - auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native(); - auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native(); + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); if (source_in == -1) source = -1; else @@ -264,16 +265,8 @@ async_pipe& async_pipe::operator=(const async_pipe & p) async_pipe& async_pipe::operator=(async_pipe && lhs) { - if (_source.native_handle() == -1) - ::close(_source.native()); - - if (_sink.native_handle() == -1) - ::close(_sink.native()); - - _source.assign(lhs._source.native_handle()); - _sink .assign(lhs._sink .native_handle()); - lhs._source.assign(-1); - lhs._sink .assign(-1); + std::swap(_source, lhs._source); + std::swap(_sink, lhs._sink); return *this; } @@ -284,8 +277,8 @@ async_pipe::operator basic_pipe<CharT, Traits>() const int sink; //cannot get the handle from a const object. - auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native(); - auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native(); + auto source_in = const_cast<::boost::asio::posix::stream_descriptor &>(_source).native_handle(); + auto sink_in = const_cast<::boost::asio::posix::stream_descriptor &>(_sink).native_handle(); if (source_in == -1) diff --git a/boost/process/detail/posix/basic_pipe.hpp b/boost/process/detail/posix/basic_pipe.hpp index 77fc90a4c1..14d140f1cc 100644 --- a/boost/process/detail/posix/basic_pipe.hpp +++ b/boost/process/detail/posix/basic_pipe.hpp @@ -29,7 +29,7 @@ class basic_pipe int _sink = -1; public: explicit basic_pipe(int source, int sink) : _source(source), _sink(sink) {} - explicit basic_pipe(int source, int sink, const std::string & name) : _source(source), _sink(sink) {} + explicit basic_pipe(int source, int sink, const std::string&) : _source(source), _sink(sink) {} typedef CharT char_type ; typedef Traits traits_type; typedef typename Traits::int_type int_type ; @@ -105,8 +105,10 @@ public: void close() { - ::close(_source); - ::close(_sink); + if (_source != -1) + ::close(_source); + if (_sink != -1) + ::close(_sink); _source = -1; _sink = -1; } diff --git a/boost/process/detail/posix/child_handle.hpp b/boost/process/detail/posix/child_handle.hpp index 44ec43ea68..8ce246d00a 100644 --- a/boost/process/detail/posix/child_handle.hpp +++ b/boost/process/detail/posix/child_handle.hpp @@ -44,7 +44,7 @@ struct child_handle return pid; } bool in_group() const {return true;} - bool in_group(std::error_code &ec) const noexcept {return true;} + bool in_group(std::error_code&) const noexcept {return true;} typedef int process_handle_t; process_handle_t process_handle() const { return pid; } diff --git a/boost/process/detail/posix/environment.hpp b/boost/process/detail/posix/environment.hpp index 1011c03a9d..58334741ae 100644 --- a/boost/process/detail/posix/environment.hpp +++ b/boost/process/detail/posix/environment.hpp @@ -1,322 +1,322 @@ -// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
-#define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_
- -#include <string>
-#include <vector>
-#include <unordered_map>
-#include <boost/process/detail/config.hpp>
-#include <algorithm>
-#include <cstdlib>
-#include <boost/process/locale.hpp>
- - -namespace boost { namespace process { namespace detail { namespace posix {
- -template<typename Char>
-class native_environment_impl
-{
- static std::vector<std::basic_string<Char>> _load()
- {
- std::vector<std::basic_string<Char>> val;
- auto p = environ;
- while (*p != nullptr)
- {
- std::string str = *p;
- val.push_back(::boost::process::detail::convert(str));
- p++;
- }
- return val;
- }
- static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec)
- {
- std::vector<Char*> val;
- val.resize(vec.size() + 1);
- std::transform(vec.begin(), vec.end(), val.begin(),
- [](std::basic_string<Char> & str)
- {
- return &str.front();
- });
- val.back() = nullptr;
- return val;
- }
- std::vector<std::basic_string<Char>> _buffer = _load();
- std::vector<Char*> _impl = _load_var(_buffer);
-public:
- using char_type = Char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = char_type **;
- - void reload()
- {
- _buffer = _load();
- _impl = _load_var(_buffer);
- }
- - string_type get(const pointer_type id) { return get(string_type(id)); }
- void set(const pointer_type id, const pointer_type value)
- {
- set(string_type(id), string_type(value));
- }
- void reset(const pointer_type id) { reset(string_type(id)); }
- - string_type get(const string_type & id)
- {
- std::string id_c = ::boost::process::detail::convert(id);
- std::string g = ::getenv(id_c.c_str());
- return ::boost::process::detail::convert(g.c_str());
- }
- void set(const string_type & id, const string_type & value)
- {
- std::string id_c = ::boost::process::detail::convert(id.c_str());
- std::string value_c = ::boost::process::detail::convert(value.c_str());
- auto res = ::setenv(id_c.c_str(), value_c.c_str(), true);
- if (res != 0)
- boost::process::detail::throw_last_error();
- }
- void reset(const string_type & id)
- {
- std::string id_c = ::boost::process::detail::convert(id.c_str());
- auto res = ::unsetenv(id_c.c_str());
- if (res != 0)
- ::boost::process::detail::throw_last_error();
- }
- - native_environment_impl() = default;
- native_environment_impl(const native_environment_impl& ) = delete;
- native_environment_impl(native_environment_impl && ) = default;
- native_environment_impl & operator=(const native_environment_impl& ) = delete;
- native_environment_impl & operator=(native_environment_impl && ) = default;
- native_handle_type _env_impl = _impl.data();
- - native_handle_type native_handle() const {return environ;}
-};
- -template<>
-class native_environment_impl<char>
-{
-public:
- using char_type = char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = char_type **;
- - void reload() {this->_env_impl = ::environ;}
- - string_type get(const pointer_type id) { return getenv(id); }
- void set(const pointer_type id, const pointer_type value)
- {
- auto res = ::setenv(id, value, 1);
- if (res != 0)
- boost::process::detail::throw_last_error();
- reload();
- }
- void reset(const pointer_type id)
- {
- auto res = ::unsetenv(id);
- if (res != 0)
- boost::process::detail::throw_last_error();
- reload();
- }
- - string_type get(const string_type & id) {return get(id.c_str());}
- void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); }
- void reset(const string_type & id) {reset(id.c_str());}
- - native_environment_impl() = default;
- native_environment_impl(const native_environment_impl& ) = delete;
- native_environment_impl(native_environment_impl && ) = default;
- native_environment_impl & operator=(const native_environment_impl& ) = delete;
- native_environment_impl & operator=(native_environment_impl && ) = default;
- native_handle_type _env_impl = environ;
- - native_handle_type native_handle() const {return ::environ;}
-};
- - - -template<typename Char>
-struct basic_environment_impl
-{
- std::vector<std::basic_string<Char>> _data {};
- static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data);
- std::vector<Char*> _env_arr{_load_var(_data)};
-public:
- using char_type = Char;
- using pointer_type = const char_type*;
- using string_type = std::basic_string<char_type>;
- using native_handle_type = Char**;
- void reload()
- {
- _env_arr = _load_var(_data);
- _env_impl = _env_arr.data();
- }
- - string_type get(const pointer_type id) {return get(string_type(id));}
- void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);}
- void reset(const pointer_type id) {reset(string_type(id));}
- - string_type get(const string_type & id);
- void set(const string_type & id, const string_type & value);
- void reset(const string_type & id);
- - basic_environment_impl(const native_environment_impl<Char> & nei);
- basic_environment_impl() = default;
- basic_environment_impl(const basic_environment_impl& rhs)
- : _data(rhs._data)
- {
- - }
- basic_environment_impl(basic_environment_impl && ) = default;
- basic_environment_impl & operator=(const basic_environment_impl& rhs)
- {
- _data = rhs._data;
- _env_arr = _load_var(_data);
- _env_impl = &*_env_arr.begin();
- return *this;
- }
- basic_environment_impl & operator=(basic_environment_impl && ) = default;
- - template<typename CharR>
- explicit inline basic_environment_impl(
- const basic_environment_impl<CharR>& rhs,
- const ::boost::process::codecvt_type & cv = ::boost::process::codecvt())
- : _data(rhs._data.size())
- {
- std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(),
- [&](const std::basic_string<CharR> & st)
- {
- return ::boost::process::detail::convert(st, cv);
- }
- - );
- reload();
- }
- - template<typename CharR>
- basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs)
- {
- _data = ::boost::process::detail::convert(rhs._data);
- _env_arr = _load_var(&*_data.begin());
- _env_impl = &*_env_arr.begin();
- return *this;
- }
- - Char ** _env_impl = &*_env_arr.data();
- - native_handle_type native_handle() const {return &_data.front();}
-};
- - -template<typename Char>
-basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei)
-{
- auto beg = nei.native_handle();
- - auto end = beg;
- while (*end != nullptr)
- end++;
- this->_data.assign(beg, end);
- reload();
-}
- - -template<typename Char>
-inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type
-{
- auto itr = std::find_if(_data.begin(), _data.end(),
- [&](const string_type & st)
- {
- if (st.size() <= id.size())
- return false;
- return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
- }
- );
- - if (itr == _data.end())
- {
- return "";
- }
- else return
- itr->data() + id.size(); //id=Thingy -> +2 points to T
-}
- -template<typename Char>
-inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value)
-{
- auto itr = std::find_if(_data.begin(), _data.end(),
- [&](const string_type & st)
- {
- if (st.size() <= id.size())
- return false;
- return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
- }
- );
- - if (itr != _data.end())
- *itr = id + equal_sign<Char>() + value;
- else
- _data.push_back(id + equal_sign<Char>() + value);
- - reload();
-}
- -template<typename Char>
-inline void basic_environment_impl<Char>::reset(const string_type &id)
-{
- auto itr = std::find_if(_data.begin(), _data.end(),
- [&](const string_type & st)
- {
- if (st.size() <= id.size())
- return false;
- return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>());
- }
- );
- if (itr != _data.end())
- {
- _data.erase(itr);//and remove it
- }
-
- reload();
- - -}
- -template<typename Char>
-std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data)
-{
- std::vector<Char*> ret;
- ret.reserve(data.size() +1);
- - for (auto & val : data)
- ret.push_back(&val.front());
- - ret.push_back(nullptr);
- return ret;
-}
- -template<typename T> constexpr T env_seperator();
-template<> constexpr char env_seperator() {return ':'; }
-template<> constexpr wchar_t env_seperator() {return L':'; }
- - -typedef int native_handle_t;
- -inline int get_id() {return getpid(); }
-inline int native_handle() {return getpid(); }
- -}
- -}
-}
-}
- - - - -#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */
+// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_ +#define BOOST_PROCESS_DETAIL_POSIX_ENVIRONMENT_HPP_ + +#include <string> +#include <vector> +#include <unordered_map> +#include <boost/process/detail/config.hpp> +#include <algorithm> +#include <cstdlib> +#include <boost/process/locale.hpp> + + +namespace boost { namespace process { namespace detail { namespace posix { + +template<typename Char> +class native_environment_impl +{ + static std::vector<std::basic_string<Char>> _load() + { + std::vector<std::basic_string<Char>> val; + auto p = environ; + while (*p != nullptr) + { + std::string str = *p; + val.push_back(::boost::process::detail::convert(str)); + p++; + } + return val; + } + static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & vec) + { + std::vector<Char*> val; + val.resize(vec.size() + 1); + std::transform(vec.begin(), vec.end(), val.begin(), + [](std::basic_string<Char> & str) + { + return &str.front(); + }); + val.back() = nullptr; + return val; + } + std::vector<std::basic_string<Char>> _buffer = _load(); + std::vector<Char*> _impl = _load_var(_buffer); +public: + using char_type = Char; + using pointer_type = const char_type*; + using string_type = std::basic_string<char_type>; + using native_handle_type = char_type **; + + void reload() + { + _buffer = _load(); + _impl = _load_var(_buffer); + } + + string_type get(const pointer_type id) { return get(string_type(id)); } + void set(const pointer_type id, const pointer_type value) + { + set(string_type(id), string_type(value)); + } + void reset(const pointer_type id) { reset(string_type(id)); } + + string_type get(const string_type & id) + { + std::string id_c = ::boost::process::detail::convert(id); + std::string g = ::getenv(id_c.c_str()); + return ::boost::process::detail::convert(g.c_str()); + } + void set(const string_type & id, const string_type & value) + { + std::string id_c = ::boost::process::detail::convert(id.c_str()); + std::string value_c = ::boost::process::detail::convert(value.c_str()); + auto res = ::setenv(id_c.c_str(), value_c.c_str(), true); + if (res != 0) + boost::process::detail::throw_last_error(); + } + void reset(const string_type & id) + { + std::string id_c = ::boost::process::detail::convert(id.c_str()); + auto res = ::unsetenv(id_c.c_str()); + if (res != 0) + ::boost::process::detail::throw_last_error(); + } + + native_environment_impl() = default; + native_environment_impl(const native_environment_impl& ) = delete; + native_environment_impl(native_environment_impl && ) = default; + native_environment_impl & operator=(const native_environment_impl& ) = delete; + native_environment_impl & operator=(native_environment_impl && ) = default; + native_handle_type _env_impl = _impl.data(); + + native_handle_type native_handle() const {return environ;} +}; + +template<> +class native_environment_impl<char> +{ +public: + using char_type = char; + using pointer_type = const char_type*; + using string_type = std::basic_string<char_type>; + using native_handle_type = char_type **; + + void reload() {this->_env_impl = ::environ;} + + string_type get(const pointer_type id) { return getenv(id); } + void set(const pointer_type id, const pointer_type value) + { + auto res = ::setenv(id, value, 1); + if (res != 0) + boost::process::detail::throw_last_error(); + reload(); + } + void reset(const pointer_type id) + { + auto res = ::unsetenv(id); + if (res != 0) + boost::process::detail::throw_last_error(); + reload(); + } + + string_type get(const string_type & id) {return get(id.c_str());} + void set(const string_type & id, const string_type & value) {set(id.c_str(), value.c_str()); } + void reset(const string_type & id) {reset(id.c_str());} + + native_environment_impl() = default; + native_environment_impl(const native_environment_impl& ) = delete; + native_environment_impl(native_environment_impl && ) = default; + native_environment_impl & operator=(const native_environment_impl& ) = delete; + native_environment_impl & operator=(native_environment_impl && ) = default; + native_handle_type _env_impl = environ; + + native_handle_type native_handle() const {return ::environ;} +}; + + + +template<typename Char> +struct basic_environment_impl +{ + std::vector<std::basic_string<Char>> _data {}; + static std::vector<Char*> _load_var(std::vector<std::basic_string<Char>> & data); + std::vector<Char*> _env_arr{_load_var(_data)}; +public: + using char_type = Char; + using pointer_type = const char_type*; + using string_type = std::basic_string<char_type>; + using native_handle_type = Char**; + void reload() + { + _env_arr = _load_var(_data); + _env_impl = _env_arr.data(); + } + + string_type get(const pointer_type id) {return get(string_type(id));} + void set(const pointer_type id, const pointer_type value) {set(string_type(id), value);} + void reset(const pointer_type id) {reset(string_type(id));} + + string_type get(const string_type & id); + void set(const string_type & id, const string_type & value); + void reset(const string_type & id); + + basic_environment_impl(const native_environment_impl<Char> & nei); + basic_environment_impl() = default; + basic_environment_impl(const basic_environment_impl& rhs) + : _data(rhs._data) + { + + } + basic_environment_impl(basic_environment_impl && ) = default; + basic_environment_impl & operator=(const basic_environment_impl& rhs) + { + _data = rhs._data; + _env_arr = _load_var(_data); + _env_impl = &*_env_arr.begin(); + return *this; + } + basic_environment_impl & operator=(basic_environment_impl && ) = default; + + template<typename CharR> + explicit inline basic_environment_impl( + const basic_environment_impl<CharR>& rhs, + const ::boost::process::codecvt_type & cv = ::boost::process::codecvt()) + : _data(rhs._data.size()) + { + std::transform(rhs._data.begin(), rhs._data.end(), _data.begin(), + [&](const std::basic_string<CharR> & st) + { + return ::boost::process::detail::convert(st, cv); + } + + ); + reload(); + } + + template<typename CharR> + basic_environment_impl & operator=(const basic_environment_impl<CharR>& rhs) + { + _data = ::boost::process::detail::convert(rhs._data); + _env_arr = _load_var(&*_data.begin()); + _env_impl = &*_env_arr.begin(); + return *this; + } + + Char ** _env_impl = &*_env_arr.data(); + + native_handle_type native_handle() const {return &_data.front();} +}; + + +template<typename Char> +basic_environment_impl<Char>::basic_environment_impl(const native_environment_impl<Char> & nei) +{ + auto beg = nei.native_handle(); + + auto end = beg; + while (*end != nullptr) + end++; + this->_data.assign(beg, end); + reload(); +} + + +template<typename Char> +inline auto basic_environment_impl<Char>::get(const string_type &id) -> string_type +{ + auto itr = std::find_if(_data.begin(), _data.end(), + [&](const string_type & st) + { + if (st.size() <= id.size()) + return false; + return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); + } + ); + + if (itr == _data.end()) + { + return ""; + } + else return + itr->data() + id.size(); //id=Thingy -> +2 points to T +} + +template<typename Char> +inline void basic_environment_impl<Char>::set(const string_type &id, const string_type &value) +{ + auto itr = std::find_if(_data.begin(), _data.end(), + [&](const string_type & st) + { + if (st.size() <= id.size()) + return false; + return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); + } + ); + + if (itr != _data.end()) + *itr = id + equal_sign<Char>() + value; + else + _data.push_back(id + equal_sign<Char>() + value); + + reload(); +} + +template<typename Char> +inline void basic_environment_impl<Char>::reset(const string_type &id) +{ + auto itr = std::find_if(_data.begin(), _data.end(), + [&](const string_type & st) + { + if (st.size() <= id.size()) + return false; + return std::equal(id.begin(), id.end(), st.begin()) && (st[id.size()] == equal_sign<Char>()); + } + ); + if (itr != _data.end()) + { + _data.erase(itr);//and remove it + } + + reload(); + + +} + +template<typename Char> +std::vector<Char*> basic_environment_impl<Char>::_load_var(std::vector<std::basic_string<Char>> & data) +{ + std::vector<Char*> ret; + ret.reserve(data.size() +1); + + for (auto & val : data) + ret.push_back(&val.front()); + + ret.push_back(nullptr); + return ret; +} + +template<typename T> constexpr T env_seperator(); +template<> constexpr char env_seperator() {return ':'; } +template<> constexpr wchar_t env_seperator() {return L':'; } + + +typedef int native_handle_t; + +inline int get_id() {return getpid(); } +inline int native_handle() {return getpid(); } + +} + +} +} +} + + + + +#endif /* BOOST_PROCESS_DETAIL_WINDOWS_ENV_STORAGE_HPP_ */ diff --git a/boost/process/detail/posix/executor.hpp b/boost/process/detail/posix/executor.hpp index 5d03fd184e..b3781f2f04 100644 --- a/boost/process/detail/posix/executor.hpp +++ b/boost/process/detail/posix/executor.hpp @@ -180,7 +180,7 @@ template<typename Sequence> class executor { template<typename HasHandler, typename UseVFork> - void internal_error_handle(const std::error_code &ec, const char* msg, HasHandler, boost::mpl::true_, UseVFork) {} + void internal_error_handle(const std::error_code&, const char*, HasHandler, boost::mpl::true_, UseVFork) {} int _pipe_sink = -1; @@ -233,7 +233,8 @@ class executor void check_error(boost::mpl::true_) {}; void check_error(boost::mpl::false_) { - throw process_error(_ec, _msg); + if (_ec) + throw process_error(_ec, _msg); } typedef typename ::boost::process::detail::has_error_handler<Sequence>::type has_error_handler; diff --git a/boost/process/detail/posix/file_descriptor.hpp b/boost/process/detail/posix/file_descriptor.hpp index 72552444b0..0dcb99caf8 100644 --- a/boost/process/detail/posix/file_descriptor.hpp +++ b/boost/process/detail/posix/file_descriptor.hpp @@ -1,76 +1,76 @@ -// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
-#define BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_
- -#include <fcntl.h>
-#include <string>
-#include <boost/filesystem/path.hpp>
- -namespace boost { namespace process { namespace detail { namespace posix {
- -struct file_descriptor
-{
- enum mode_t
- {
- read = 1,
- write = 2,
- read_write = 3
- };
- - - file_descriptor() = default;
- explicit file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write)
- : file_descriptor(p.native(), mode)
- {
- }
- - explicit file_descriptor(const std::string & path , mode_t mode = read_write)
- : file_descriptor(path.c_str(), mode) {}
- - - explicit file_descriptor(const char* path, mode_t mode = read_write)
- : _handle(create_file(path, mode))
- {
- - }
- - file_descriptor(const file_descriptor & ) = delete;
- file_descriptor(file_descriptor && ) = default;
- - file_descriptor& operator=(const file_descriptor & ) = delete;
- file_descriptor& operator=(file_descriptor && ) = default;
- - ~file_descriptor()
- {
- if (_handle != -1)
- ::close(_handle);
- }
- - int handle() const { return _handle;}
- -private:
- static int create_file(const char* name, mode_t mode )
- {
- switch(mode)
- {
- case read:
- return ::open(name, O_RDONLY);
- case write:
- return ::open(name, O_WRONLY | O_CREAT, 0660);
- case read_write:
- return ::open(name, O_RDWR | O_CREAT, 0660);
- default:
- return -1;
- }
- }
- - int _handle = -1;
-};
- -}}}}
- -#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */
+// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_ +#define BOOST_PROCESS_DETAIL_POSIX_FILE_DESCRIPTOR_HPP_ + +#include <fcntl.h> +#include <string> +#include <boost/filesystem/path.hpp> + +namespace boost { namespace process { namespace detail { namespace posix { + +struct file_descriptor +{ + enum mode_t + { + read = 1, + write = 2, + read_write = 3 + }; + + + file_descriptor() = default; + explicit file_descriptor(const boost::filesystem::path& p, mode_t mode = read_write) + : file_descriptor(p.native(), mode) + { + } + + explicit file_descriptor(const std::string & path , mode_t mode = read_write) + : file_descriptor(path.c_str(), mode) {} + + + explicit file_descriptor(const char* path, mode_t mode = read_write) + : _handle(create_file(path, mode)) + { + + } + + file_descriptor(const file_descriptor & ) = delete; + file_descriptor(file_descriptor && ) = default; + + file_descriptor& operator=(const file_descriptor & ) = delete; + file_descriptor& operator=(file_descriptor && ) = default; + + ~file_descriptor() + { + if (_handle != -1) + ::close(_handle); + } + + int handle() const { return _handle;} + +private: + static int create_file(const char* name, mode_t mode ) + { + switch(mode) + { + case read: + return ::open(name, O_RDONLY); + case write: + return ::open(name, O_WRONLY | O_CREAT, 0660); + case read_write: + return ::open(name, O_RDWR | O_CREAT, 0660); + default: + return -1; + } + } + + int _handle = -1; +}; + +}}}} + +#endif /* BOOST_PROCESS_DETAIL_WINDOWS_FILE_DESCRIPTOR_HPP_ */ diff --git a/boost/process/detail/posix/file_in.hpp b/boost/process/detail/posix/file_in.hpp index c3ceeeead2..7ddd71684b 100644 --- a/boost/process/detail/posix/file_in.hpp +++ b/boost/process/detail/posix/file_in.hpp @@ -1,40 +1,40 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
-#define BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP
- -#include <boost/process/pipe.hpp>
-#include <boost/process/detail/posix/handler.hpp>
-#include <boost/process/detail/posix/file_descriptor.hpp>
-#include <cstdio>
-#include <unistd.h>
- -namespace boost { namespace process { namespace detail { namespace posix {
- -struct file_in : handler_base_ext
-{
- file_descriptor file;
- int handle = file.handle();
- - template<typename T>
- file_in(T&& t) : file(std::forward<T>(t)) {}
- file_in(FILE * f) : handle(fileno(f)) {}
- - template <class WindowsExecutor>
- void on_exec_setup(WindowsExecutor &e) const
- {
- if (::dup2(handle, STDIN_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- }
-};
- -}}}}
- -#endif
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP +#define BOOST_PROCESS_DETAIL_POSIX_FILE_IN_HPP + +#include <boost/process/pipe.hpp> +#include <boost/process/detail/posix/handler.hpp> +#include <boost/process/detail/posix/file_descriptor.hpp> +#include <cstdio> +#include <unistd.h> + +namespace boost { namespace process { namespace detail { namespace posix { + +struct file_in : handler_base_ext +{ + file_descriptor file; + int handle = file.handle(); + + template<typename T> + file_in(T&& t) : file(std::forward<T>(t)) {} + file_in(FILE * f) : handle(fileno(f)) {} + + template <class WindowsExecutor> + void on_exec_setup(WindowsExecutor &e) const + { + if (::dup2(handle, STDIN_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + } +}; + +}}}} + +#endif diff --git a/boost/process/detail/posix/file_out.hpp b/boost/process/detail/posix/file_out.hpp index 6fef732598..8e3d4eb716 100644 --- a/boost/process/detail/posix/file_out.hpp +++ b/boost/process/detail/posix/file_out.hpp @@ -1,65 +1,65 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_PROCESS_POSIX_FILE_OUT_HPP
-#define BOOST_PROCESS_POSIX_FILE_OUT_HPP
+#ifndef BOOST_PROCESS_POSIX_FILE_OUT_HPP +#define BOOST_PROCESS_POSIX_FILE_OUT_HPP -#include <boost/process/detail/posix/handler.hpp>
-#include <boost/process/detail/posix/file_descriptor.hpp>
+#include <boost/process/detail/posix/handler.hpp> +#include <boost/process/detail/posix/file_descriptor.hpp> -#include <unistd.h>
-namespace boost { namespace process { namespace detail { namespace posix {
+#include <unistd.h> +namespace boost { namespace process { namespace detail { namespace posix { -template<int p1, int p2>
-struct file_out : handler_base_ext
-{
- file_descriptor file;
- int handle = file.handle();
+template<int p1, int p2> +struct file_out : handler_base_ext +{ + file_descriptor file; + int handle = file.handle(); - template<typename T>
- file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write), handle(file.handle()) {}
- file_out(FILE * f) : handle(fileno(f)) {}
+ template<typename T> + file_out(T&& t) : file(std::forward<T>(t), file_descriptor::write), handle(file.handle()) {} + file_out(FILE * f) : handle(fileno(f)) {} - template <typename Executor>
- void on_exec_setup(Executor &e) const;
-};
+ template <typename Executor> + void on_exec_setup(Executor &e) const; +}; -template<>
-template<typename Executor>
-void file_out<1,-1>::on_exec_setup(Executor &e) const
-{
- if (::dup2(handle, STDOUT_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
-}
+template<> +template<typename Executor> +void file_out<1,-1>::on_exec_setup(Executor &e) const +{ + if (::dup2(handle, STDOUT_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); +} -template<>
-template<typename Executor>
-void file_out<2,-1>::on_exec_setup(Executor &e) const
-{
- if (::dup2(handle, STDERR_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
-}
+template<> +template<typename Executor> +void file_out<2,-1>::on_exec_setup(Executor &e) const +{ + if (::dup2(handle, STDERR_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); +} -template<>
-template<typename Executor>
-void file_out<1,2>::on_exec_setup(Executor &e) const
-{
- if (::dup2(handle, STDOUT_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+template<> +template<typename Executor> +void file_out<1,2>::on_exec_setup(Executor &e) const +{ + if (::dup2(handle, STDOUT_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); - if (::dup2(handle, STDERR_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
+ if (::dup2(handle, STDERR_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); -}
+} -}}}}
+}}}} -#endif
+#endif diff --git a/boost/process/detail/posix/group_ref.hpp b/boost/process/detail/posix/group_ref.hpp index d46e631fe7..730450fe11 100644 --- a/boost/process/detail/posix/group_ref.hpp +++ b/boost/process/detail/posix/group_ref.hpp @@ -28,7 +28,7 @@ struct group_ref : handler_base_ext {} template <class Executor> - void on_exec_setup(Executor& exec) const + void on_exec_setup(Executor&) const { if (grp.grp == -1) ::setpgid(0, 0); diff --git a/boost/process/detail/posix/handler.hpp b/boost/process/detail/posix/handler.hpp index 506db4e649..5ca3989a0f 100644 --- a/boost/process/detail/posix/handler.hpp +++ b/boost/process/detail/posix/handler.hpp @@ -1,74 +1,74 @@ -// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
-#define BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_
+#ifndef BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ +#define BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ -#include <boost/process/detail/handler_base.hpp>
+#include <boost/process/detail/handler_base.hpp> -namespace boost { namespace process { namespace detail { namespace posix {
+namespace boost { namespace process { namespace detail { namespace posix { -//does not extend anything.
-struct handler_base_ext : handler_base
-{
- template<typename Executor>
- void on_fork_error (Executor &, const std::error_code&) const {}
+//does not extend anything. +struct handler_base_ext : handler_base +{ + template<typename Executor> + void on_fork_error (Executor &, const std::error_code&) const {} - template<typename Executor>
- void on_exec_setup (Executor &) const {}
+ template<typename Executor> + void on_exec_setup (Executor &) const {} - template<typename Executor>
- void on_exec_error (Executor &, const std::error_code&) const {}
-};
+ template<typename Executor> + void on_exec_error (Executor &, const std::error_code&) const {} +}; -template <class Handler>
-struct on_fork_error_ : handler_base_ext
-{
- explicit on_fork_error_(Handler handler) : handler_(handler) {}
+template <class Handler> +struct on_fork_error_ : handler_base_ext +{ + explicit on_fork_error_(Handler handler) : handler_(handler) {} - template <class Executor>
- void on_fork_error(Executor &e, const std::error_code &ec) const
- {
- handler_(e, ec);
- }
-private:
- Handler handler_;
-};
+ template <class Executor> + void on_fork_error(Executor &e, const std::error_code &ec) const + { + handler_(e, ec); + } +private: + Handler handler_; +}; -template <class Handler>
-struct on_exec_setup_ : handler_base_ext
-{
- explicit on_exec_setup_(Handler handler) : handler_(handler) {}
+template <class Handler> +struct on_exec_setup_ : handler_base_ext +{ + explicit on_exec_setup_(Handler handler) : handler_(handler) {} - template <class Executor>
- void on_exec_setup(Executor &e) const
- {
- handler_(e);
- }
-private:
- Handler handler_;
-};
+ template <class Executor> + void on_exec_setup(Executor &e) const + { + handler_(e); + } +private: + Handler handler_; +}; -template <class Handler>
-struct on_exec_error_ : handler_base_ext
-{
- explicit on_exec_error_(Handler handler) : handler_(handler) {}
+template <class Handler> +struct on_exec_error_ : handler_base_ext +{ + explicit on_exec_error_(Handler handler) : handler_(handler) {} - template <class Executor>
- void on_exec_error(Executor &e, const std::error_code &ec) const
- {
- handler_(e, ec);
- }
-private:
- Handler handler_;
-};
+ template <class Executor> + void on_exec_error(Executor &e, const std::error_code &ec) const + { + handler_(e, ec); + } +private: + Handler handler_; +}; -}}}}
+}}}} -#endif /* BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ */
+#endif /* BOOST_PROCESS_DETAIL_POSIX_HANDLER_HPP_ */ diff --git a/boost/process/detail/posix/io_service_ref.hpp b/boost/process/detail/posix/io_context_ref.hpp index ced1d51033..603fd59a16 100644 --- a/boost/process/detail/posix/io_service_ref.hpp +++ b/boost/process/detail/posix/io_context_ref.hpp @@ -1,155 +1,114 @@ -// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
-#define BOOST_PROCESS_POSIX_IO_SERVICE_REF_HPP_
- -#include <boost/process/detail/posix/handler.hpp>
-#include <boost/process/detail/posix/async_handler.hpp>
-#include <boost/asio/io_service.hpp>
-#include <boost/asio/signal_set.hpp>
- -#include <boost/fusion/algorithm/iteration/for_each.hpp>
-#include <boost/fusion/algorithm/transformation/filter_if.hpp>
-#include <boost/fusion/algorithm/transformation/transform.hpp>
-#include <boost/fusion/view/transform_view.hpp>
-#include <boost/fusion/container/vector/convert.hpp>
- - -#include <functional>
-#include <type_traits>
-#include <memory>
-#include <vector>
-#include <sys/wait.h>
- -namespace boost { namespace process { namespace detail { namespace posix {
- -template<typename Executor>
-struct on_exit_handler_transformer
-{
- Executor & exec;
- on_exit_handler_transformer(Executor & exec) : exec(exec) {}
- template<typename Sig>
- struct result;
- - template<typename T>
- struct result<on_exit_handler_transformer<Executor>(T&)>
- {
- typedef typename T::on_exit_handler_t type;
- };
- - template<typename T>
- auto operator()(T& t) const -> typename T::on_exit_handler_t
- {
- return t.on_exit_handler(exec);
- }
-};
- -template<typename Executor>
-struct async_handler_collector
-{
- Executor & exec;
- std::vector<std::function<void(int, const std::error_code & ec)>> &handlers;
- - - async_handler_collector(Executor & exec,
- std::vector<std::function<void(int, const std::error_code & ec)>> &handlers)
- : exec(exec), handlers(handlers) {}
- - template<typename T>
- void operator()(T & t) const
- {
- handlers.push_back(t.on_exit_handler(exec));
- };
-};
- -//Also set's up waiting for the exit, so it can close async stuff.
-struct io_service_ref : handler_base_ext
-{
- io_service_ref(boost::asio::io_service & ios) : ios(ios)
- {
- - }
- boost::asio::io_service &get() {return ios;};
- - boost::asio::signal_set *signal_p = nullptr;
- - template <class Executor>
- void on_setup(Executor& exec)
- {
- //must be on the heap so I can move it into the lambda.
- auto asyncs = boost::fusion::filter_if<
- is_async_handler<
- typename std::remove_reference< boost::mpl::_ > ::type
- >>(exec.seq);
- - //ok, check if there are actually any.
- if (boost::fusion::empty(asyncs))
- return;
- - std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
- funcs.reserve(boost::fusion::size(asyncs));
- boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs));
- - wait_handler wh(std::move(funcs), ios, exec.exit_status);
- - signal_p = wh.signal_.get();
- signal_p->async_wait(std::move(wh));
- - }
- - template <class Executor>
- void on_error(Executor & exec, const std::error_code & ec) const
- {
- if (signal_p != nullptr)
- {
- boost::system::error_code ec;
- signal_p->cancel(ec);
- }
- }
- - struct wait_handler
- {
- std::shared_ptr<boost::asio::signal_set> signal_;
- std::vector<std::function<void(int, const std::error_code & ec)>> funcs;
- std::shared_ptr<std::atomic<int>> exit_status;
- - wait_handler(const wait_handler & ) = default;
- wait_handler(wait_handler && ) = default;
- wait_handler(
- std::vector<std::function<void(int, const std::error_code & ec)>> && funcs,
- boost::asio::io_service & ios,
- const std::shared_ptr<std::atomic<int>> &exit_status)
- : signal_(new boost::asio::signal_set(ios, SIGCHLD)),
- funcs(std::move(funcs)),
- exit_status(exit_status)
- {
- - }
- void operator()(const boost::system::error_code & ec_in, int /*signal*/)
- {
- if (ec_in.value() == boost::asio::error::operation_aborted)
- return;
- - - int status;
- ::wait(&status);
- - std::error_code ec(ec_in.value(), std::system_category());
- int val = WEXITSTATUS(status);
- exit_status->store(status);
- - for (auto & func : funcs)
- func(val, ec);
- }
- - };
-private:
- boost::asio::io_service &ios;
-};
- -}}}}
- -#endif /* BOOST_PROCESS_WINDOWS_IO_SERVICE_REF_HPP_ */
+// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_ +#define BOOST_PROCESS_POSIX_IO_CONTEXT_REF_HPP_ + +#include <boost/process/detail/posix/handler.hpp> +#include <boost/process/detail/posix/async_handler.hpp> +#include <boost/asio/io_context.hpp> + +#include <boost/fusion/algorithm/iteration/for_each.hpp> +#include <boost/fusion/algorithm/transformation/filter_if.hpp> +#include <boost/fusion/algorithm/transformation/transform.hpp> +#include <boost/fusion/view/transform_view.hpp> +#include <boost/fusion/container/vector/convert.hpp> + + +#include <boost/process/detail/posix/sigchld_service.hpp> + +#include <functional> +#include <type_traits> +#include <memory> +#include <vector> +#include <sys/wait.h> + +namespace boost { namespace process { namespace detail { namespace posix { + +template<typename Executor> +struct on_exit_handler_transformer +{ + Executor & exec; + on_exit_handler_transformer(Executor & exec) : exec(exec) {} + template<typename Sig> + struct result; + + template<typename T> + struct result<on_exit_handler_transformer<Executor>(T&)> + { + typedef typename T::on_exit_handler_t type; + }; + + template<typename T> + auto operator()(T& t) const -> typename T::on_exit_handler_t + { + return t.on_exit_handler(exec); + } +}; + +template<typename Executor> +struct async_handler_collector +{ + Executor & exec; + std::vector<std::function<void(int, const std::error_code & ec)>> &handlers; + + + async_handler_collector(Executor & exec, + std::vector<std::function<void(int, const std::error_code & ec)>> &handlers) + : exec(exec), handlers(handlers) {} + + template<typename T> + void operator()(T & t) const + { + handlers.push_back(t.on_exit_handler(exec)); + }; +}; + +//Also set's up waiting for the exit, so it can close async stuff. +struct io_context_ref : handler_base_ext +{ + io_context_ref(boost::asio::io_context & ios) : ios(ios) + { + + } + boost::asio::io_context &get() {return ios;}; + + template <class Executor> + void on_success(Executor& exec) + { + //must be on the heap so I can move it into the lambda. + auto asyncs = boost::fusion::filter_if< + is_async_handler< + typename std::remove_reference< boost::mpl::_ > ::type + >>(exec.seq); + + //ok, check if there are actually any. + if (boost::fusion::empty(asyncs)) + return; + + std::vector<std::function<void(int, const std::error_code & ec)>> funcs; + funcs.reserve(boost::fusion::size(asyncs)); + boost::fusion::for_each(asyncs, async_handler_collector<Executor>(exec, funcs)); + + auto & es = exec.exit_status; + + auto wh = [funcs, es](int val, const std::error_code & ec) + { + es->store(val); + for (auto & func : funcs) + func(WEXITSTATUS(val), ec); + }; + + sigchld_service.async_wait(exec.pid, std::move(wh)); + } + +private: + boost::asio::io_context &ios; + boost::process::detail::posix::sigchld_service &sigchld_service = boost::asio::use_service<boost::process::detail::posix::sigchld_service>(ios); +}; + +}}}} + +#endif /* BOOST_PROCESS_WINDOWS_IO_CONTEXT_REF_HPP_ */ diff --git a/boost/process/detail/posix/null_in.hpp b/boost/process/detail/posix/null_in.hpp index 9f082054c6..33ced810b1 100644 --- a/boost/process/detail/posix/null_in.hpp +++ b/boost/process/detail/posix/null_in.hpp @@ -1,35 +1,35 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
-#define BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP
+#ifndef BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP +#define BOOST_PROCESS_DETAIL_POSIX_NULL_IN_HPP -#include <boost/process/pipe.hpp>
-#include <boost/process/detail/posix/handler.hpp>
-#include <boost/process/detail/posix/file_descriptor.hpp>
-#include <unistd.h>
+#include <boost/process/pipe.hpp> +#include <boost/process/detail/posix/handler.hpp> +#include <boost/process/detail/posix/file_descriptor.hpp> +#include <unistd.h> -namespace boost { namespace process { namespace detail { namespace posix {
+namespace boost { namespace process { namespace detail { namespace posix { -struct null_in : handler_base_ext
-{
- file_descriptor source{"/dev/null", file_descriptor::read};
+struct null_in : handler_base_ext +{ + file_descriptor source{"/dev/null", file_descriptor::read}; -public:
- template <class Executor>
- void on_exec_setup(Executor &e) const
- {
- if (::dup2(source.handle(), STDIN_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- }
-};
+public: + template <class Executor> + void on_exec_setup(Executor &e) const + { + if (::dup2(source.handle(), STDIN_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + } +}; -}}}}
+}}}} -#endif
+#endif diff --git a/boost/process/detail/posix/null_out.hpp b/boost/process/detail/posix/null_out.hpp index ed4f915f35..3874475f4d 100644 --- a/boost/process/detail/posix/null_out.hpp +++ b/boost/process/detail/posix/null_out.hpp @@ -1,58 +1,58 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_POSIX_PIPE_OUT_HPP
-#define BOOST_PROCESS_POSIX_PIPE_OUT_HPP
- -#include <boost/process/detail/posix/handler.hpp>
-#include <boost/process/detail/posix/file_descriptor.hpp>
- -#include <unistd.h>
-namespace boost { namespace process { namespace detail { namespace posix {
- -template<int p1, int p2>
-struct null_out : handler_base_ext
-{
- file_descriptor sink{"/dev/null", file_descriptor::write};
-
- template <typename Executor>
- void on_exec_setup(Executor &e) const;
-};
- -template<>
-template<typename Executor>
-void null_out<1,-1>::on_exec_setup(Executor &e) const
-{
- if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
-}
- -template<>
-template<typename Executor>
-void null_out<2,-1>::on_exec_setup(Executor &e) const
-{
- if (::dup2(sink.handle(), STDERR_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
-}
- -template<>
-template<typename Executor>
-void null_out<1,2>::on_exec_setup(Executor &e) const
-{
- if (::dup2(sink.handle(), STDOUT_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- - if (::dup2(sink.handle(), STDERR_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
-}
- -}}}}
- -#endif
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_PIPE_OUT_HPP +#define BOOST_PROCESS_POSIX_PIPE_OUT_HPP + +#include <boost/process/detail/posix/handler.hpp> +#include <boost/process/detail/posix/file_descriptor.hpp> + +#include <unistd.h> +namespace boost { namespace process { namespace detail { namespace posix { + +template<int p1, int p2> +struct null_out : handler_base_ext +{ + file_descriptor sink{"/dev/null", file_descriptor::write}; + + template <typename Executor> + void on_exec_setup(Executor &e) const; +}; + +template<> +template<typename Executor> +void null_out<1,-1>::on_exec_setup(Executor &e) const +{ + if (::dup2(sink.handle(), STDOUT_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); +} + +template<> +template<typename Executor> +void null_out<2,-1>::on_exec_setup(Executor &e) const +{ + if (::dup2(sink.handle(), STDERR_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); +} + +template<> +template<typename Executor> +void null_out<1,2>::on_exec_setup(Executor &e) const +{ + if (::dup2(sink.handle(), STDOUT_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + + if (::dup2(sink.handle(), STDERR_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); +} + +}}}} + +#endif diff --git a/boost/process/detail/posix/on_exit.hpp b/boost/process/detail/posix/on_exit.hpp index d3160aff32..eb79a81b6b 100644 --- a/boost/process/detail/posix/on_exit.hpp +++ b/boost/process/detail/posix/on_exit.hpp @@ -1,35 +1,35 @@ -// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#ifndef BOOST_PROCESS_POSIX_ON_EXIT_HPP_
-#define BOOST_PROCESS_POSIX_ON_EXIT_HPP_
+#ifndef BOOST_PROCESS_POSIX_ON_EXIT_HPP_ +#define BOOST_PROCESS_POSIX_ON_EXIT_HPP_ -#include <boost/process/detail/config.hpp>
-#include <boost/process/detail/handler_base.hpp>
-#include <boost/process/detail/posix/async_handler.hpp>
-#include <system_error>
-#include <functional>
+#include <boost/process/detail/config.hpp> +#include <boost/process/detail/handler_base.hpp> +#include <boost/process/detail/posix/async_handler.hpp> +#include <system_error> +#include <functional> -namespace boost { namespace process { namespace detail { namespace posix {
+namespace boost { namespace process { namespace detail { namespace posix { -struct on_exit_ : boost::process::detail::posix::async_handler
-{
- std::function<void(int, const std::error_code&)> handler;
- on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler)
- {
+struct on_exit_ : boost::process::detail::posix::async_handler +{ + std::function<void(int, const std::error_code&)> handler; + on_exit_(const std::function<void(int, const std::error_code&)> & handler) : handler(handler) + { - }
+ } - template<typename Executor>
- std::function<void(int, const std::error_code&)> on_exit_handler(Executor & exec)
- {
- return handler;
+ template<typename Executor> + std::function<void(int, const std::error_code&)> on_exit_handler(Executor&) + { + return handler; - };
-};
+ }; +}; -}}}}
-#endif /* BOOST_PROCESS_POSIX_ON_EXIT_HPP_ */
+}}}} +#endif /* BOOST_PROCESS_POSIX_ON_EXIT_HPP_ */ diff --git a/boost/process/detail/posix/pipe_in.hpp b/boost/process/detail/posix/pipe_in.hpp index fa294cf310..18ca856573 100644 --- a/boost/process/detail/posix/pipe_in.hpp +++ b/boost/process/detail/posix/pipe_in.hpp @@ -1,90 +1,90 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_POSIX_PIPE_IN_HPP
-#define BOOST_PROCESS_POSIX_PIPE_IN_HPP
- -#include <boost/process/pipe.hpp>
-#include <boost/process/detail/posix/handler.hpp>
-#include <unistd.h>
- - -namespace boost { namespace process { namespace detail { namespace posix {
- -struct pipe_in : handler_base_ext
-{
- int source;
- int sink; //opposite end
- - pipe_in(int sink, int source) : source(source), sink(sink) {}
- - - template<typename T>
- pipe_in(T & p) : source(p.native_source()), sink(p.native_sink())
- {
- p.assign_source(-1);
- }
- - template<typename Executor>
- void on_error(Executor &, const std::error_code &) const
- {
- ::close(source);
- }
- - template<typename Executor>
- void on_success(Executor &) const
- {
- ::close(source);
- }
- - template <class Executor>
- void on_exec_setup(Executor &e) const
- {
- if (::dup2(source, STDIN_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- ::close(source);
- ::close(sink);
- }
- -};
- -class async_pipe;
- -struct async_pipe_in : public pipe_in
-{
- async_pipe &pipe;
- - template<typename AsyncPipe>
- async_pipe_in(AsyncPipe & p) : pipe_in(p.native_sink(), p.native_source()), pipe(p)
- {
- }
- - template<typename Pipe, typename Executor>
- static void close(Pipe & pipe, Executor &)
- {
- boost::system::error_code ec;
- std::move(pipe).source().close(ec);
- }
- - template<typename Executor>
- void on_error(Executor & exec, const std::error_code &)
- {
- close(pipe, exec);
- }
- - template<typename Executor>
- void on_success(Executor &exec)
- {
- close(pipe, exec);
- }
-};
- -}}}}
- -#endif
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_POSIX_PIPE_IN_HPP +#define BOOST_PROCESS_POSIX_PIPE_IN_HPP + +#include <boost/process/pipe.hpp> +#include <boost/process/detail/posix/handler.hpp> +#include <unistd.h> + + +namespace boost { namespace process { namespace detail { namespace posix { + +struct pipe_in : handler_base_ext +{ + int source; + int sink; //opposite end + + pipe_in(int sink, int source) : source(source), sink(sink) {} + + + template<typename T> + pipe_in(T & p) : source(p.native_source()), sink(p.native_sink()) + { + p.assign_source(-1); + } + + template<typename Executor> + void on_error(Executor &, const std::error_code &) const + { + ::close(source); + } + + template<typename Executor> + void on_success(Executor &) const + { + ::close(source); + } + + template <class Executor> + void on_exec_setup(Executor &e) const + { + if (::dup2(source, STDIN_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + ::close(source); + ::close(sink); + } + +}; + +class async_pipe; + +struct async_pipe_in : public pipe_in +{ + async_pipe &pipe; + + template<typename AsyncPipe> + async_pipe_in(AsyncPipe & p) : pipe_in(p.native_sink(), p.native_source()), pipe(p) + { + } + + template<typename Pipe, typename Executor> + static void close(Pipe & pipe, Executor &) + { + boost::system::error_code ec; + std::move(pipe).source().close(ec); + } + + template<typename Executor> + void on_error(Executor & exec, const std::error_code &) + { + close(pipe, exec); + } + + template<typename Executor> + void on_success(Executor &exec) + { + close(pipe, exec); + } +}; + +}}}} + +#endif diff --git a/boost/process/detail/posix/pipe_out.hpp b/boost/process/detail/posix/pipe_out.hpp index 0148c19d26..9f7da9464b 100644 --- a/boost/process/detail/posix/pipe_out.hpp +++ b/boost/process/detail/posix/pipe_out.hpp @@ -1,116 +1,116 @@ -// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
-// Copyright (c) 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling
-// Copyright (c) 2016 Klemens D. Morgenstern
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- -#ifndef BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
-#define BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP
- -#include <boost/process/pipe.hpp>
-#include <boost/process/detail/posix/handler.hpp>
-#include <unistd.h>
- -namespace boost { namespace process { namespace detail { namespace posix {
- -template<int p1, int p2>
-struct pipe_out : handler_base_ext
-{
- int sink;
- int source; //opposite end
- - pipe_out(int sink, int source) : sink(sink), source(source) {}
- - template<typename T>
- pipe_out(T & p) : sink(p.native_sink()), source(p.native_source())
- {
- p.assign_sink(-1);
- }
- - template<typename Executor>
- void on_error(Executor &, const std::error_code &) const
- {
- ::close(sink);
- }
- - template<typename Executor>
- void on_success(Executor &) const
- {
- ::close(sink);
- }
- - template <typename Executor>
- void on_exec_setup(Executor &e) const;
-};
- -template<>
-template<typename Executor>
-void pipe_out<1,-1>::on_exec_setup(Executor &e) const
-{
- if (::dup2(sink, STDOUT_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup3() failed");
- ::close(sink);
- ::close(source);
-}
- -template<>
-template<typename Executor>
-void pipe_out<2,-1>::on_exec_setup(Executor &e) const
-{
- if (::dup2(sink, STDERR_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- ::close(sink);
- ::close(source);
-}
- -template<>
-template<typename Executor>
-void pipe_out<1,2>::on_exec_setup(Executor &e) const
-{
- if (::dup2(sink, STDOUT_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- if (::dup2(sink, STDERR_FILENO) == -1)
- e.set_error(::boost::process::detail::get_last_error(), "dup2() failed");
- ::close(sink);
- ::close(source);
-}
- -class async_pipe;
- -template<int p1, int p2>
-struct async_pipe_out : public pipe_out<p1, p2>
-{
- async_pipe &pipe;
- template<typename AsyncPipe>
- async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink(), p.native_source()), pipe(p)
- {
- }
- - template<typename Pipe, typename Executor>
- static void close(Pipe & pipe, Executor &)
- {
- boost::system::error_code ec;
- std::move(pipe).sink().close(ec);
- }
- - template<typename Executor>
- void on_error(Executor & exec, const std::error_code &)
- {
- close(pipe, exec);
- }
- - template<typename Executor>
- void on_success(Executor &exec)
- {
- close(pipe, exec);
- }
-};
- - -}}}}
- -#endif
+// Copyright (c) 2006, 2007 Julio M. Merino Vidal +// Copyright (c) 2008 Ilya Sokolov, Boris Schaeling +// Copyright (c) 2009 Boris Schaeling +// Copyright (c) 2010 Felipe Tanus, Boris Schaeling +// Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling +// Copyright (c) 2016 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP +#define BOOST_PROCESS_DETAIL_POSIX_PIPE_OUT_HPP + +#include <boost/process/pipe.hpp> +#include <boost/process/detail/posix/handler.hpp> +#include <unistd.h> + +namespace boost { namespace process { namespace detail { namespace posix { + +template<int p1, int p2> +struct pipe_out : handler_base_ext +{ + int sink; + int source; //opposite end + + pipe_out(int sink, int source) : sink(sink), source(source) {} + + template<typename T> + pipe_out(T & p) : sink(p.native_sink()), source(p.native_source()) + { + p.assign_sink(-1); + } + + template<typename Executor> + void on_error(Executor &, const std::error_code &) const + { + ::close(sink); + } + + template<typename Executor> + void on_success(Executor &) const + { + ::close(sink); + } + + template <typename Executor> + void on_exec_setup(Executor &e) const; +}; + +template<> +template<typename Executor> +void pipe_out<1,-1>::on_exec_setup(Executor &e) const +{ + if (::dup2(sink, STDOUT_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup3() failed"); + ::close(sink); + ::close(source); +} + +template<> +template<typename Executor> +void pipe_out<2,-1>::on_exec_setup(Executor &e) const +{ + if (::dup2(sink, STDERR_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + ::close(sink); + ::close(source); +} + +template<> +template<typename Executor> +void pipe_out<1,2>::on_exec_setup(Executor &e) const +{ + if (::dup2(sink, STDOUT_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + if (::dup2(sink, STDERR_FILENO) == -1) + e.set_error(::boost::process::detail::get_last_error(), "dup2() failed"); + ::close(sink); + ::close(source); +} + +class async_pipe; + +template<int p1, int p2> +struct async_pipe_out : public pipe_out<p1, p2> +{ + async_pipe &pipe; + template<typename AsyncPipe> + async_pipe_out(AsyncPipe & p) : pipe_out<p1, p2>(p.native_sink(), p.native_source()), pipe(p) + { + } + + template<typename Pipe, typename Executor> + static void close(Pipe & pipe, Executor &) + { + boost::system::error_code ec; + std::move(pipe).sink().close(ec); + } + + template<typename Executor> + void on_error(Executor & exec, const std::error_code &) + { + close(pipe, exec); + } + + template<typename Executor> + void on_success(Executor &exec) + { + close(pipe, exec); + } +}; + + +}}}} + +#endif diff --git a/boost/process/detail/posix/search_path.hpp b/boost/process/detail/posix/search_path.hpp index 1ce5c65575..633cf0702e 100644 --- a/boost/process/detail/posix/search_path.hpp +++ b/boost/process/detail/posix/search_path.hpp @@ -24,7 +24,6 @@ inline boost::filesystem::path search_path( const boost::filesystem::path &filename, const std::vector<boost::filesystem::path> &path) { - std::string result; for (const boost::filesystem::path & pp : path) { auto p = pp / filename; diff --git a/boost/process/detail/posix/sigchld_service.hpp b/boost/process/detail/posix/sigchld_service.hpp new file mode 100644 index 0000000000..7fee01e075 --- /dev/null +++ b/boost/process/detail/posix/sigchld_service.hpp @@ -0,0 +1,113 @@ +// Copyright (c) 2017 Klemens D. Morgenstern +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +#ifndef BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_ +#define BOOST_PROCESS_DETAIL_POSIX_SIGCHLD_SERVICE_HPP_ + +#include <boost/asio/signal_set.hpp> +#include <boost/asio/strand.hpp> +#include <boost/optional.hpp> +#include <signal.h> +#include <functional> +#include <sys/wait.h> + +namespace boost { namespace process { namespace detail { namespace posix { + +class sigchld_service : public boost::asio::detail::service_base<sigchld_service> +{ + boost::asio::io_context::strand _strand{get_io_context()}; + boost::asio::signal_set _signal_set{get_io_context(), SIGCHLD}; + + std::vector<std::pair<::pid_t, std::function<void(int, std::error_code)>>> _receivers; + inline void _handle_signal(const boost::system::error_code & ec); +public: + sigchld_service(boost::asio::io_context & io_context) + : boost::asio::detail::service_base<sigchld_service>(io_context) + { + } + + template <typename SignalHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(SignalHandler, + void (int, std::error_code)) + async_wait(::pid_t pid, SignalHandler && handler) + { + boost::asio::async_completion< + SignalHandler, void(boost::system::error_code)> init{handler}; + auto & h = init.completion_handler; + _strand.post( + [this, pid, h] + { + if (_receivers.empty()) + _signal_set.async_wait( + [this](const boost::system::error_code & ec, int) + { + _strand.post([this,ec]{this->_handle_signal(ec);}); + }); + _receivers.emplace_back(pid, h); + }); + + return init.result.get(); + } + void shutdown_service() override + { + _receivers.clear(); + } + + void cancel() + { + _signal_set.cancel(); + } + void cancel(boost::system::error_code & ec) + { + _signal_set.cancel(ec); + } +}; + + +void sigchld_service::_handle_signal(const boost::system::error_code & ec) +{ + std::error_code ec_{ec.value(), std::system_category()}; + + if (ec_) + { + for (auto & r : _receivers) + r.second(-1, ec_); + return; + } + int status; + int pid = ::waitpid(0, &status, WNOHANG); + + auto itr = std::find_if(_receivers.begin(), _receivers.end(), + [&pid](const std::pair<::pid_t, std::function<void(int, std::error_code)>> & p) + { + return p.first == pid; + }); + if (itr != _receivers.cend()) + { + _strand.get_io_context().wrap(itr->second)(status, ec_); + _receivers.erase(itr); + } + if (!_receivers.empty()) + { + _signal_set.async_wait( + [this](const boost::system::error_code & ec, int) + { + _strand.post([ec]{}); + this->_handle_signal(ec); + }); + } +} + + +} +} +} +} + + + + +#endif diff --git a/boost/process/detail/posix/wait_for_exit.hpp b/boost/process/detail/posix/wait_for_exit.hpp index bf25e2a3d8..308aaf6908 100644 --- a/boost/process/detail/posix/wait_for_exit.hpp +++ b/boost/process/detail/posix/wait_for_exit.hpp @@ -15,7 +15,7 @@ #include <system_error> #include <sys/types.h> #include <sys/wait.h> - +#include <unistd.h> namespace boost { namespace process { namespace detail { namespace posix { @@ -26,9 +26,11 @@ inline void wait(const child_handle &p, int & exit_code) do { ret = ::waitpid(p.pid, &status, 0); - } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status))); + } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) boost::process::detail::throw_last_error("waitpid(2) failed"); + if (WIFSIGNALED(status)) + throw process_error(std::error_code(), "process terminated due to receipt of a signal"); exit_code = status; } @@ -41,7 +43,7 @@ inline void wait(const child_handle &p, int & exit_code, std::error_code &ec) no { ret = ::waitpid(p.pid, &status, 0); } - while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status))); + while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) ec = boost::process::detail::get_last_error(); @@ -67,26 +69,27 @@ inline bool wait_for( auto start = std::chrono::system_clock::now(); auto time_out = start + rel_time; - bool time_out_occured = false; + bool timed_out; do { - ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG); - if (std::chrono::system_clock::now() >= time_out) + ret = ::waitpid(p.pid, &status, WNOHANG); + if (ret == 0) { - time_out_occured = true; - break; + timed_out = std::chrono::system_clock::now() >= time_out; + if (timed_out) + return false; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); - + while ((ret == 0) || + ((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) boost::process::detail::throw_last_error("waitpid(2) failed"); - + exit_code = status; - return !time_out_occured; + return true; } @@ -103,20 +106,25 @@ inline bool wait_for( auto start = std::chrono::system_clock::now(); auto time_out = start + rel_time; + bool timed_out; - bool time_out_occured = false; do { - ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG); - if (std::chrono::system_clock::now() >= time_out) + ret = ::waitpid(p.pid, &status, WNOHANG); + if (ret == 0) { - time_out_occured = true; - break; + timed_out = std::chrono::system_clock::now() >= time_out; + if (timed_out) + return false; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + while ((ret == 0) || + (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)))); + + if (timed_out && (ret == -1)) + return false; if (ret == -1) ec = boost::process::detail::get_last_error(); @@ -126,68 +134,79 @@ inline bool wait_for( exit_code = status; } - return !time_out_occured; + return true; } -template< class Rep, class Period > +template< class Clock, class Duration > inline bool wait_until( const child_handle &p, int & exit_code, - const std::chrono::duration<Rep, Period>& time_out) + const std::chrono::time_point<Clock, Duration>& time_out) { pid_t ret; int status; - bool time_out_occured = false; + bool timed_out; do { - ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG); - if (std::chrono::system_clock::now() >= time_out) + ret = ::waitpid(p.pid, &status, WNOHANG); + if (ret == 0) { - time_out_occured = true; - break; + timed_out = std::chrono::system_clock::now() >= time_out; + if (timed_out) + return false; } - } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + } + while ((ret == 0) || + (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)))); + if (timed_out && !WIFEXITED(status)) + return false; + if (ret == -1) boost::process::detail::throw_last_error("waitpid(2) failed"); - exit_code = status; - return !time_out_occured; + return true; } -template< class Rep, class Period > +template< class Clock, class Duration > inline bool wait_until( const child_handle &p, int & exit_code, - const std::chrono::duration<Rep, Period>& time_out, + const std::chrono::time_point<Clock, Duration>& time_out, std::error_code & ec) noexcept { pid_t ret; int status; - bool time_out_occured = false; + bool timed_out; + do { - ret = ::waitpid(p.pid, &status, WUNTRACED | WNOHANG); - if (std::chrono::system_clock::now() >= time_out) + ret = ::waitpid(p.pid, &status, WNOHANG); + if (ret == 0) { - time_out_occured = true; - break; + timed_out = std::chrono::system_clock::now() >= time_out; + if (timed_out) + return false; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + while ((ret == 0) || + (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status)))); + + + if (timed_out && !WIFEXITED(status)) + return false; if (ret == -1) ec = boost::process::detail::get_last_error(); @@ -197,7 +216,7 @@ inline bool wait_until( exit_code = status; } - return !time_out_occured; + return true; } }}}} diff --git a/boost/process/detail/posix/wait_group.hpp b/boost/process/detail/posix/wait_group.hpp index 8b768ffc14..172fe06b5b 100644 --- a/boost/process/detail/posix/wait_group.hpp +++ b/boost/process/detail/posix/wait_group.hpp @@ -25,9 +25,11 @@ inline void wait(const group_handle &p) do { ret = ::waitpid(-p.grp, &status, 0); - } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status))); + } while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) boost::process::detail::throw_last_error("waitpid(2) failed"); + if (WIFSIGNALED(status)) + throw process_error(std::error_code(), "process group terminated due to receipt of a signal"); } inline void wait(const group_handle &p, std::error_code &ec) noexcept @@ -39,10 +41,12 @@ inline void wait(const group_handle &p, std::error_code &ec) noexcept { ret = ::waitpid(-p.grp, &status, 0); } - while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status))); + while (((ret == -1) && (errno == EINTR)) || (ret != -1 && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) ec = boost::process::detail::get_last_error(); + else if (WIFSIGNALED(status)) + ec = std::make_error_code(std::errc::no_such_process); else ec.clear(); @@ -70,13 +74,14 @@ inline bool wait_for( break; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + while (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) boost::process::detail::throw_last_error("waitpid(2) failed"); - + if (WIFSIGNALED(status)) + throw process_error(std::error_code(), "process group terminated due to receipt of a signal"); return !time_out_occured; } @@ -105,12 +110,14 @@ inline bool wait_for( break; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + while (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) ec = boost::process::detail::get_last_error(); + else if (WIFSIGNALED(status)) + ec = std::make_error_code(std::errc::no_such_process); else ec.clear(); @@ -128,8 +135,6 @@ inline bool wait_until( pid_t ret; int status; - auto start = std::chrono::system_clock::now(); - bool time_out_occured = false; do { @@ -140,12 +145,14 @@ inline bool wait_until( break; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + while (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) boost::process::detail::throw_last_error("waitpid(2) failed"); + if (WIFSIGNALED(status)) + throw process_error(std::error_code(), "process group terminated due to receipt of a signal"); return !time_out_occured; @@ -162,8 +169,6 @@ inline bool wait_until( pid_t ret; int status; - auto start = std::chrono::system_clock::now(); - bool time_out_occured = false; do { @@ -174,12 +179,14 @@ inline bool wait_until( break; } } - while (((ret == -1) && errno == EINTR) || - ((ret != -1) && !WIFEXITED(status))); + while (((ret == -1) && errno == EINTR) || + ((ret != -1) && !WIFEXITED(status) && !WIFSIGNALED(status))); if (ret == -1) ec = boost::process::detail::get_last_error(); + else if (WIFSIGNALED(status)) + ec = std::make_error_code(std::errc::no_such_process); else ec.clear(); |