Boost.Process is a rather small library to make it as simple as possible for developers to create, control and communicate with processes. For a better idea how the library's structure looks like the following diagram has been created.
The most important classes are
child: They implement the Context and Process concepts Boost.Process is built on. While Context is used to setup the overall context the new process will run in, Process describes any process. Currently it's only possible to access children via
child and the current process via
self. As of today there is no way to access other processes.
In order to communicate with a child
postream are used. They can be accessed via
child and represent input and output streams. By default all streams are closed when a child is started. The context has to be configured appropriately to redirect streams if a parent should be able to communicate with a child.
A process can wait for a child to terminate. When it is terminated
status enables the process to fetch the exit code of the child.
If more than one child should be created and the children should be connected with each other
pipeline_entry is used to specify the context of every child in the pipeline. As a pipeline consists of more than one process
children is used to manage the entire pipeline. It's then for example not possible to communicate via
postream with each and every child in the pipeline but only with the first and last child (as the children in the pipeline communicate with each other).
As Boost.Process is platform-independent by default only those features are supported which are available on all platforms. As POSIX and Windows platforms support more features additional classes are provided in case platform-specific features should be used.
There are basically four steps when a child is spawned:
Before a process can be created
boost/process/context.hpp) must be setup. This includes specifying what should happen with the input, output and error streams (eg. if they should be closed or redirected) and how the environment table which contains environment variables should look like. The classes
boost/process/win32_context.hpp) support additional options which are only available on the respective platforms (eg. setting the uid on POSIX platforms or passing a STARTUPINFO object on Windows platforms).
After a context has been created it is passed to a function which starts the process and returns
child. The header file
boost/process/operations.hpp provides the template function
launch which requires the caller to pass the name of the executable (typically
std::string), a set of arguments (typically
std::vector<std::string> and the
context object. The template functions
boost/process/posix_operations.hpp) must be called if the classes
win32_context have been used to setup a context. While
launch returns a
posix_launch returns a
posix_child object (in
win32_child object (in
If the context has been setup to redirect streams it is possible to access the child's input, output and error streams. The library provides two classes
boost/process/postream.hpp) which are derived from
std::ostream and thus behave like standard C++ streams. They can be used to write to the child's input stream and to read from the child's output and error streams (always assuming that the context has been setup in a way that these streams are redirected). Of course it's not required to communicate with a child at all - this step is optional.
After having created a context, started a process and possibly communicated with the child it's possible to wait for the child to terminate, terminate the child explicitly or just forget about the child. If a process waits for the child to terminate and the child terminates a
status object (in
boost/process/status.hpp) is returned which enables a process to check the exit code of the child (eg. if it returned EXIT_SUCCESS or EXIT_FAILURE). On POSIX platforms
posix_child returns a
posix_status object (in
boost/process/posix_status.hpp) to check for example if the child dumped core.
postream objects are used to communicate with a child all read/write operations are blocking just like with any other standard C++ stream. If for example a process reads from a child and the child doesn't write data the read operation blocks until new data is written by the child.
While there is no support for asynchronous I/O in
postream the underlying handle can be fetched and passed to
boost::asio::windows::stream_handle which are provided by Asio. On Windows platforms it is required to define BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE as on Windows anonymous pipes which are used by default to redirect streams between processes don't support asynchronous I/O.
For details check the tutorials for an example how to use asynchronous I/O with Boost.Asio.