Files

4.5 KiB
Raw Permalink Blame History

Launcher

The process creation is done by a process_launcher. The constructor of process will use the default_launcher, which varies by system. There are additional launcher available on most systems.

Name Summary Default on Available on

windows::default_launcher

CreateProcessW

windows

windows

windows::as_user_launcher

CreateProcessAsUserW

windows

windows::with_logon_launcher

CreateProcessWithLogonW

windows

windows::with_token_launcher

CreateProcessWithTokenW

windows

posix::default_launcher

fork & an error pipe

most of posix

posix

posix::fork_and_forget

fork without error pipe

posix

posix::vfork_launcher

vfork

posix

A launcher is invoked through the call operator.

auto l = windows::as_user_launcher((HANDLE)0xDEADBEEF);
asio::io_context ctx;
boost::system::error_code ec;
auto proc = l(ctx, ec, "C:\\User\\boost\\Downloads\\totally_not_a_virus.exe", {});

The launcher will call certain functions on the initializer if theyre present, as documented below. The initializer are used to modify the process behaviour.

Linux Launchers

The default launchers on linux open an internal pipe to communicate errors that occur after forking back to the parent process.

Note
A pipe can be used if one end is open on the parent, the other on the child. This allows the parents to select on his pipe-end to know if the child exited.

This can be prevented by using the fork_and_forget_launcher. Alternatively, the vfork_launcher can report errors directly back to the parent process.

Thus some calls to the initializers occur after forking from the child process.

struct custom_initializer
{
    // called before a call to fork. A returned error will cancel the launch.
    template<typename Launcher>
    error_code on_setup(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line));

    // called for every initializer if an error occurred during setup or process creation
    template<typename Launcher>
    void on_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line),
                  const error_code & ec);

    // called after successful process creation
    template<typename Launcher>
    void on_success(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line));

    // called for every initializer if an error occurred when forking, in addition to on_error.
    template<typename Launcher>
    void on_fork_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line),
                       const error_code & ec);


    // called before a call to execve. A returned error will cancel the launch. Called from the child process.
    template<typename Launcher>
    error_code on_exec_setup(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line));


    // called after a failed call to execve from the child process.
    template<typename Launcher>
    void on_exec_error(Launcher & launcher, const filesystem::path &executable, const char * const * (&cmd_line));
};

The call sequence on success:

posix success

The call sequence when fork fails:

posix fork err

The call sequence when exec fails:

posix exec err

The launcher will close all non-whitelisted file descriptors after on_exec_setup.

Windows Launchers

Windows launchers are pretty straight forward, they will call the following functions on the initializer if present.

struct custom_initializer
{
    // called before a call to CreateProcess. A returned error will cancel the launch.
    template<typename Launcher>
    error_code on_setup(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line);

    // called for every initializer if an error occurred during setup or process creation
    template<typename Launcher>
    void on_error(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line,
                  const error_code & ec);

    // called after successful process creation
    template<typename Launcher>
    void on_success(Launcher & launcher, const filesystem::path &executable, std::wstring &cmd_line);

};
Note
All the additional launchers for windows inherit default_launcher.

The call sequence is as follows:

image::windows_exec.svg '''