File indexing completed on 2025-01-18 09:50:11
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&, 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