123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157 |
- // 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 <boost/asio/post.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_context*/
- Args && ...args)
- {
- IoService & ios = ::boost::process::detail::get_io_context_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&)
- {
- boost::asio::post(ios.get_executor(), [&]{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_context*/
- Args && ...args)
- {
- IoService ios;
- child c(ios, std::forward<Args>(args)...);
- if (!c.valid())
- return -1;
- ios.run();
- if (c.running())
- c.wait();
- return c.exit_code();
- }
- template<typename IoService, typename ...Args>
- inline int system_impl(
- std::false_type, /*needs ios*/
- std::true_type, /*has io_context*/
- 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_context*/
- 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_context object,
- the system function will create one and run it. When the io_context is passed to the function,
- the system function will check if it is active, and call the io_context::run function if not.
- */
- template<typename ...Args>
- inline int system(Args && ...args)
- {
- typedef typename ::boost::process::detail::needs_io_context<Args...>::type
- need_ios;
- typedef typename ::boost::process::detail::has_io_context<Args...>::type
- has_ios;
- return ::boost::process::detail::system_impl<boost::asio::io_context>(
- need_ios(), has_ios(),
- std::forward<Args>(args)...);
- }
- }}
- #endif
|