Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:11

0001 // Copyright (c) 2022 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 #ifndef BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP
0006 #define BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP
0007 
0008 #include <boost/process/v2/posix/default_launcher.hpp>
0009 #include <unistd.h>
0010 
0011 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0012 
0013 namespace posix
0014 {
0015 
0016 
0017 /// A launcher using vfork instead of fork. 
0018 struct vfork_launcher :  default_launcher
0019 {
0020     vfork_launcher() = default;
0021 
0022     template<typename ExecutionContext, typename Args, typename ... Inits>
0023     auto operator()(ExecutionContext & context,
0024                     const typename std::enable_if<std::is_convertible<
0025                             ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
0026                             filesystem::path >::type & executable,
0027                     Args && args,
0028                     Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
0029     {
0030         error_code ec;
0031         auto proc =  (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
0032 
0033         if (ec)
0034             v2::detail::throw_error(ec, "default_launcher");
0035 
0036         return proc;
0037     }
0038 
0039 
0040     template<typename ExecutionContext, typename Args, typename ... Inits>
0041     auto operator()(ExecutionContext & context,
0042                     error_code & ec,
0043                     const typename std::enable_if<std::is_convertible<
0044                             ExecutionContext&, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context&>::value,
0045                             filesystem::path >::type & executable,
0046                     Args && args,
0047                     Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
0048     {
0049         return (*this)(context.get_executor(), executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
0050     }
0051 
0052     template<typename Executor, typename Args, typename ... Inits>
0053     auto operator()(Executor exec,
0054                     const typename std::enable_if<
0055                             BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
0056                             BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
0057                             filesystem::path >::type & executable,
0058                     Args && args,
0059                     Inits && ... inits ) -> basic_process<Executor>
0060     {
0061         error_code ec;
0062         auto proc =  (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
0063 
0064         if (ec)
0065             v2::detail::throw_error(ec, "default_launcher");
0066 
0067         return proc;
0068     }
0069 
0070     template<typename Executor, typename Args, typename ... Inits>
0071     auto operator()(Executor exec,
0072                     error_code & ec,
0073                     const typename std::enable_if<
0074                             BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::is_executor<Executor>::value ||
0075                             BOOST_PROCESS_V2_ASIO_NAMESPACE::is_executor<Executor>::value,
0076                             filesystem::path >::type & executable,
0077                     Args && args,
0078                     Inits && ... inits ) -> basic_process<Executor>
0079     {
0080         auto argv = this->build_argv_(executable, std::forward<Args>(args));
0081 
0082         ec = detail::on_setup(*this, executable, argv, inits ...);
0083         if (ec)
0084         {
0085             detail::on_error(*this, executable, argv, ec, inits...);
0086             return basic_process<Executor>(exec);
0087         }
0088 
0089         auto & ctx = BOOST_PROCESS_V2_ASIO_NAMESPACE::query(
0090                 exec, BOOST_PROCESS_V2_ASIO_NAMESPACE::execution::context);
0091         ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_prepare);
0092         pid = ::vfork();
0093         if (pid == -1)
0094         {
0095             ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
0096             detail::on_fork_error(*this, executable, argv, ec, inits...);
0097             detail::on_error(*this, executable, argv, ec, inits...);
0098 
0099             BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
0100             return basic_process<Executor>{exec};
0101         }
0102         else if (pid == 0)
0103         {
0104             ec = detail::on_exec_setup(*this, executable, argv, inits...);
0105             if (!ec)
0106                 close_all_fds(ec);
0107             if (!ec)
0108                 ::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
0109 
0110             BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category())
0111             detail::on_exec_error(*this, executable, argv, ec, inits...);
0112             ::_exit(EXIT_FAILURE);
0113             return basic_process<Executor>{exec};
0114         }
0115         ctx.notify_fork(BOOST_PROCESS_V2_ASIO_NAMESPACE::execution_context::fork_parent);
0116 
0117         if (ec)
0118         {
0119             detail::on_error(*this, executable, argv, ec, inits...);
0120             return basic_process<Executor>{exec};
0121         }
0122 
0123         basic_process<Executor> proc(exec, pid);
0124         detail::on_success(*this, executable, argv, ec, inits...);
0125         return proc;
0126 
0127     }
0128 };
0129 
0130 
0131 }
0132 
0133 BOOST_PROCESS_V2_END_NAMESPACE
0134 
0135 #endif //BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP