Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:48:47

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_FORK_AND_FORGET_LAUNCHER_HPP
0006 #define BOOST_PROCESS_V2_POSIX_FORK_AND_FORGET_LAUNCHER_HPP
0007 
0008 #include <boost/process/v2/posix/default_launcher.hpp>
0009 
0010 BOOST_PROCESS_V2_BEGIN_NAMESPACE
0011 
0012 namespace posix
0013 {
0014 
0015 /// A posix fork launcher that ignores errors after `fork`.
0016 struct fork_and_forget_launcher : default_launcher
0017 {
0018     fork_and_forget_launcher() = default;
0019 
0020     template<typename ExecutionContext, typename Args, typename ... Inits>
0021     auto operator()(ExecutionContext & context,
0022                     const typename std::enable_if<is_convertible<
0023                             ExecutionContext&, net::execution_context&>::value,
0024                             filesystem::path >::type & executable,
0025                     Args && args,
0026                     Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
0027     {
0028         error_code ec;
0029         auto proc =  (*this)(context, ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
0030 
0031         if (ec)
0032             v2::detail::throw_error(ec, "fork_and_forget_launcher");
0033 
0034         return proc;
0035     }
0036 
0037 
0038     template<typename ExecutionContext, typename Args, typename ... Inits>
0039     auto operator()(ExecutionContext & context,
0040                     error_code & ec,
0041                     const typename std::enable_if<is_convertible<
0042                             ExecutionContext&, net::execution_context&>::value,
0043                             filesystem::path >::type & executable,
0044                     Args && args,
0045                     Inits && ... inits ) -> basic_process<typename ExecutionContext::executor_type>
0046     {
0047         return (*this)(context.get_executor(), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
0048     }
0049 
0050     template<typename Executor, typename Args, typename ... Inits>
0051     auto operator()(Executor exec,
0052                     const typename std::enable_if<
0053                             net::execution::is_executor<Executor>::value ||
0054                             net::is_executor<Executor>::value,
0055                             filesystem::path >::type & executable,
0056                     Args && args,
0057                     Inits && ... inits ) -> basic_process<Executor>
0058     {
0059         error_code ec;
0060         auto proc =  (*this)(std::move(exec), ec, executable, std::forward<Args>(args), std::forward<Inits>(inits)...);
0061 
0062         if (ec)
0063             v2::detail::throw_error(ec, "fork_and_forget_launcher");
0064 
0065         return proc;
0066     }
0067 
0068     template<typename Executor, typename Args, typename ... Inits>
0069     auto operator()(Executor exec,
0070                     error_code & ec,
0071                     const typename std::enable_if<
0072                             net::execution::is_executor<Executor>::value ||
0073                             net::is_executor<Executor>::value,
0074                             filesystem::path >::type & executable,
0075                     Args && args,
0076                     Inits && ... inits ) -> basic_process<Executor>
0077     {
0078         auto argv = this->build_argv_(executable, std::forward<Args>(args));
0079         {
0080             ec = detail::on_setup(*this, executable, argv, inits ...);
0081             if (ec)
0082             {
0083                 detail::on_error(*this, executable, argv, ec, inits...);
0084                 return basic_process<Executor>(exec);
0085             }
0086 
0087             auto & ctx = net::query(
0088                     exec, net::execution::context);
0089 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0090             ctx.notify_fork(net::execution_context::fork_prepare);
0091 #endif
0092             pid = ::fork();
0093             if (pid == -1)
0094             {
0095 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0096                 ctx.notify_fork(net::execution_context::fork_parent);
0097 #endif
0098                 detail::on_fork_error(*this, executable, argv, ec, inits...);
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 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0108                 ctx.notify_fork(net::execution_context::fork_child);
0109 #endif
0110                 ec = detail::on_exec_setup(*this, executable, argv, inits...);
0111                 if (!ec)
0112                     close_all_fds(ec);
0113                 if (!ec)
0114                     ::execve(executable.c_str(), const_cast<char * const *>(argv), const_cast<char * const *>(env));
0115 
0116                 BOOST_PROCESS_V2_ASSIGN_EC(ec, errno, system_category());
0117                 detail::on_exec_error(*this, executable, argv, ec, inits...);
0118                 ::exit(EXIT_FAILURE);
0119                 return basic_process<Executor>{exec};
0120             }
0121 #if !defined(BOOST_PROCESS_V2_DISABLE_NOTIFY_FORK)
0122             ctx.notify_fork(net::execution_context::fork_parent);
0123 #endif
0124             if (ec)
0125             {
0126                 detail::on_error(*this, executable, argv, ec, inits...);
0127                 do { ::waitpid(pid, nullptr, 0); } while (errno == EINTR);
0128                 return basic_process<Executor>{exec};
0129             }
0130         }
0131         basic_process<Executor> proc(exec, pid);
0132         detail::on_success(*this, executable, argv, ec, inits...);
0133         return proc;
0134 
0135     }
0136 };
0137 
0138 
0139 }
0140 
0141 BOOST_PROCESS_V2_END_NAMESPACE
0142 
0143 
0144 #endif //BOOST_PROCESS_V2_POSIX_FORK_AND_FORGET_LAUNCHER_HPP