diff options
Diffstat (limited to 'boost/process/system.hpp')
-rw-r--r-- | boost/process/system.hpp | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/boost/process/system.hpp b/boost/process/system.hpp new file mode 100644 index 0000000000..bdcac88713 --- /dev/null +++ b/boost/process/system.hpp @@ -0,0 +1,154 @@ +// 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) + +/** + * \file boost/process/system.hpp + * + * Defines a system function. + */ + +#ifndef BOOST_PROCESS_SYSTEM_HPP +#define BOOST_PROCESS_SYSTEM_HPP + +#include <boost/process/detail/config.hpp> +#include <boost/process/detail/on_exit.hpp> +#include <boost/process/child.hpp> +#include <boost/process/detail/async_handler.hpp> +#include <boost/process/detail/execute_impl.hpp> +#include <type_traits> +#include <mutex> +#include <condition_variable> + +#if defined(BOOST_POSIX_API) +#include <boost/process/posix.hpp> +#endif + +namespace boost { + +namespace process { + +namespace detail +{ + +struct system_impl_success_check : handler +{ + bool succeeded = false; + + template<typename Exec> + void on_success(Exec &) { succeeded = true; } +}; + +template<typename IoService, typename ...Args> +inline int system_impl( + std::true_type, /*needs ios*/ + std::true_type, /*has io_service*/ + Args && ...args) +{ + IoService & ios = ::boost::process::detail::get_io_service_var(args...); + + system_impl_success_check check; + + std::atomic_bool exited{false}; + + child c(std::forward<Args>(args)..., + check, + ::boost::process::on_exit( + [&](int, const std::error_code&) + { + ios.post([&]{exited.store(true);}); + })); + if (!c.valid() || !check.succeeded) + return -1; + + while (!exited.load()) + ios.poll(); + + return c.exit_code(); +} + +template<typename IoService, typename ...Args> +inline int system_impl( + std::true_type, /*needs ios */ + std::false_type, /*has io_service*/ + Args && ...args) +{ + IoService ios; + child c(ios, std::forward<Args>(args)...); + if (!c.valid()) + return -1; + + ios.run(); + return c.exit_code(); +} + + +template<typename IoService, typename ...Args> +inline int system_impl( + std::false_type, /*needs ios*/ + std::true_type, /*has io_service*/ + Args && ...args) +{ + child c(std::forward<Args>(args)...); + if (!c.valid()) + return -1; + c.wait(); + return c.exit_code(); +} + +template<typename IoService, typename ...Args> +inline int system_impl( + std::false_type, /*has async */ + std::false_type, /*has io_service*/ + Args && ...args) +{ + child c(std::forward<Args>(args)... +#if defined(BOOST_POSIX_API) + ,::boost::process::posix::sig.dfl() +#endif + ); + if (!c.valid()) + return -1; + c.wait(); + return c.exit_code(); +} + +} + +/** Launches a process and waits for its exit. +It works as std::system, though it allows +all the properties boost.process provides. It will execute the process and wait for it's exit; then return the exit_code. + +\code{.cpp} +int ret = system("ls"); +\endcode + +\attention Using this function with synchronous pipes leads to many potential deadlocks. + +When using this function with an asynchronous properties and NOT passing an io_service object, +the system function will create one and run it. When the io_service is passed to the function, +the system function will check if it is active, and call the io_service::run function if not. + +*/ +template<typename ...Args> +inline int system(Args && ...args) +{ + typedef typename ::boost::process::detail::needs_io_service<Args...>::type + need_ios; + typedef typename ::boost::process::detail::has_io_service<Args...>::type + has_ios; + return ::boost::process::detail::system_impl<boost::asio::io_service>( + need_ios(), has_ios(), + std::forward<Args>(args)...); +} + + +}} +#endif + |