Boost C++ Libraries Home Libraries People FAQ More


Design overview

Creating, controlling and communicating with a child
Support for blocking and asynchronous I/O

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 context and 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 pistream and 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 pistream and 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.

Creating, controlling and communicating with a child

There are basically four steps when a child is spawned:

  • Before a process can be created context (in 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 posix_context (in boost/process/posix_context.hpp) and win32_context (in 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 win32_launch (in boost/process/win32_operations.hpp) and posix_launch (in boost/process/posix_operations.hpp) must be called if the classes posix_context and win32_context have been used to setup a context. While launch returns a child object, posix_launch returns a posix_child object (in boost/process/posix_child.hpp) and win32_launch a win32_child object (in boost/process/win32_child.hpp).

  • 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 pistream (in boost/process/pistream.hpp) and postream (in boost/process/postream.hpp) which are derived from std::istream respectively 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.

Support for blocking and asynchronous I/O

When pistream and 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 pistream and postream the underlying handle can be fetched and passed to boost::asio::posix::stream_descriptor respectively 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.