File indexing completed on 2025-09-16 08:48:32
0001
0002
0003
0004
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
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