Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:48:32

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&, net::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&, net::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(), ec, 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                             net::execution::is_executor<Executor>::value ||
0056                             net::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                             net::execution::is_executor<Executor>::value ||
0075                             net::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 = net::query(exec, net::execution::context);
0090 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0091         ctx.notify_fork(net::execution_context::fork_prepare);
0092 #endif
0093         pid = ::vfork();
0094         if (pid == -1)
0095         {
0096 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0097             ctx.notify_fork(net::execution_context::fork_parent);
0098 #endif
0099             detail::on_fork_error(*this, executable, argv, ec, inits...);
0100             detail::on_error(*this, executable, argv, ec, inits...);
0101 
0102             BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
0103             return basic_process<Executor>{exec};
0104         }
0105         else if (pid == 0)
0106         {
0107             ec = detail::on_exec_setup(*this, executable, argv, inits...);
0108             if (!ec)
0109                 close_all_fds(ec);
0110             if (!ec)
0111                 ::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
0112 
0113             BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
0114             detail::on_exec_error(*this, executable, argv, ec, inits...);
0115             ::_exit(EXIT_FAILURE);
0116             return basic_process<Executor>{exec};
0117         }
0118 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0119         ctx.notify_fork(net::execution_context::fork_parent);
0120 #endif
0121         if (ec)
0122         {
0123             detail::on_error(*this, executable, argv, ec, inits...);
0124             do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
0125             return basic_process<Executor>{exec};
0126         }
0127 
0128         basic_process<Executor> proc(exec, pid);
0129         detail::on_success(*this, executable, argv, ec, inits...);
0130         return proc;
0131 
0132     }
0133 };
0134 
0135 
0136 }
0137 
0138 BOOST_PROCESS_V2_END_NAMESPACE
0139 
0140 #endif //BOOST_PROCESS_V2_POSIX_VFORK_LAUNCHER_HPP