...one of the most highly
regarded and expertly designed C++ library projects in the
world.
— Herb Sutter and Andrei
Alexandrescu, C++
Coding Standards
boost::process::extend::posix_executor — The posix executor type.
// In header: <boost/process/extend.hpp>
template<typename Sequence>
struct posix_executor {
// public member functions
const std::error_code & error() const;
void set_error(const std::error_code &, const std::string &);
void set_error(const std::error_code &, const char *);
// public data members
Sequence & seq; // A reference to the actual initializer-sequence.
const char * exe; // A pointer to the name of the executable.
char *const * cmd_line; // A pointer to the argument-vector.
char ** env; // A pointer to the environment variables, as default it is set to environ
pid_t pid; // The pid of the process - it will be -1 before invoking fork, and after forking either 0 for the new process or a positive value if in the current process. */.
std::shared_ptr< std::atomic< int > > exit_status; // This shared-pointer holds the exit code. It's done this way, so it can be shared between an asio::io_context
and child.
};
This type represents the posix executor and can be used for overloading in a custom handler.
Note | |
---|---|
It is an alias for the implementation on posix, and a forward-declaration on windows. |
As information for extension development, here is the structure of the process launching (in pseudo-code and uml)
for (auto & s : seq) s.on_setup(*this); if (error()) { for (auto & s : seq) s.on_error(*this, error()); return child(); } pid = fork() on_setup(*this); if (pid == -1) //fork error { set_error(get_last_error()); for (auto & s : seq) s.on_fork_error(*this, error()); for (auto & s : seq) s.on_error(*this, error()); return child() } else if (pid == 0) //child process { for (auto & s : seq) s.on_exec_setup(*this); execve(exe, cmd_line, env); auto ec = get_last_error(); for (auto & s : seq) s.on_exec_error(*this); unspecified();//here the error is send to the father process interally std::exit(EXIT_FAILURE); return child(); //for C++ compliance } child c(pid, exit_code); unspecified();//here, we read the the error from the child process if (error()) for (auto & s : seq) s.on_error(*this, error()); else for (auto & s : seq) s.on_success(*this); //now we check again, because a on_success handler might've errored. if (error()) { for (auto & s : seq) s.on_error(*this, error()); return child(); } else return c;
Note | |
---|---|
Error handling if execve fails is done through a pipe, unless ignore_error is used. |
typename Sequence
The used initializer-sequence, it is fulfills the boost.fusion sequence concept.
posix_executor
public member functionsconst std::error_code & error() const;This function returns a const reference to the error state of the executor.
void set_error(const std::error_code & ec, const std::string & msg);
This function can be used to report an error to the executor. This will be handled according to the configuration of the executor, i.e. it might throw an exception.
Note | |
---|---|
This is the required way to handle errors in initializers. |
void set_error(const std::error_code & ec, const char * msg);
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.