|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r65795 - in sandbox/SOC/2010/process: boost/process boost/process/detail libs/process/doc libs/process/example libs/process/test
From: boris_at_[hidden]
Date: 2010-10-06 18:51:52
Author: bschaeling
Date: 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
New Revision: 65795
URL: http://svn.boost.org/trac/boost/changeset/65795
Log:
Made boost::process::context::setup a boost::function delegate
Fixed bug in boost::process::status on Windows
Updated documentation
Text files modified:
sandbox/SOC/2010/process/boost/process/child.hpp | 8 --------
sandbox/SOC/2010/process/boost/process/context.hpp | 28 ++++++----------------------
sandbox/SOC/2010/process/boost/process/detail/basic_status_service.hpp | 6 ++++++
sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp | 33 ++++++++++++++++++---------------
sandbox/SOC/2010/process/boost/process/detail/status_impl.hpp | 23 +++++++++++++++++++++++
sandbox/SOC/2010/process/boost/process/detail/windows_helpers.hpp | 12 ++++++++----
sandbox/SOC/2010/process/boost/process/handle.hpp | 9 +++++----
sandbox/SOC/2010/process/boost/process/operations.hpp | 8 +++++---
sandbox/SOC/2010/process/boost/process/pid_type.hpp | 2 +-
sandbox/SOC/2010/process/boost/process/process.hpp | 13 ++++++++-----
sandbox/SOC/2010/process/boost/process/self.hpp | 6 ++++--
sandbox/SOC/2010/process/boost/process/stream_behavior.hpp | 4 +---
sandbox/SOC/2010/process/boost/process/stream_type.hpp | 2 +-
sandbox/SOC/2010/process/libs/process/doc/asyncio.qbk | 2 +-
sandbox/SOC/2010/process/libs/process/doc/communication.qbk | 10 +++-------
sandbox/SOC/2010/process/libs/process/doc/context.qbk | 17 ++++++++++-------
sandbox/SOC/2010/process/libs/process/doc/future.qbk | 3 +--
sandbox/SOC/2010/process/libs/process/doc/introduction.qbk | 2 +-
sandbox/SOC/2010/process/libs/process/doc/posix.qbk | 18 ++++++++----------
sandbox/SOC/2010/process/libs/process/doc/process.qbk | 14 +++++---------
sandbox/SOC/2010/process/libs/process/doc/userstreambehaviors.qbk | 4 ----
sandbox/SOC/2010/process/libs/process/doc/windows.qbk | 6 +++---
sandbox/SOC/2010/process/libs/process/example/chroot_setup.cpp | 19 ++++++++-----------
sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp | 4 ++--
sandbox/SOC/2010/process/libs/process/example/startupinfo_setup.cpp | 23 ++++++++++-------------
sandbox/SOC/2010/process/libs/process/test/child.cpp | 21 +++++++++------------
sandbox/SOC/2010/process/libs/process/test/wait.cpp | 2 ++
27 files changed, 149 insertions(+), 150 deletions(-)
Modified: sandbox/SOC/2010/process/boost/process/child.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/child.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/child.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -33,8 +33,6 @@
#include <boost/process/pid_type.hpp>
#include <boost/process/stream_id.hpp>
#include <boost/process/handle.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/assert.hpp>
#include <map>
namespace boost {
@@ -61,12 +59,6 @@
* Creates a new child object that represents the just spawned child
* process \a id.
*
- * The \a fhstdin, \a fhstdout and \a fhstderr file handles represent
- * the parent's handles used to communicate with the corresponding
- * data streams. They needn't be valid but their availability must
- * match the redirections configured by the launcher that spawned this
- * process.
- *
* This operation is only available on Windows systems.
*/
child(handle hprocess, std::map<stream_id, handle> handles)
Modified: sandbox/SOC/2010/process/boost/process/context.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/context.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/context.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -23,7 +23,6 @@
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
-# include <vector>
# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
@@ -105,39 +104,24 @@
#endif
}
-#if defined(BOOST_PROCESS_DOXYGEN)
+#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
/**
* Setups a child process.
*
* This is an extension point to support more configuration options for
- * child processes. You override setup() in a user-defined context class
- * which should be derived from this class.
+ * child processes. You can initialize \a setup with a user-defined function
+ * which is called when a child process is created.
*
* On POSIX platforms setup() is called in the child process. That's why in
* a multithreaded application only async-signal-safe functions must be
- * called in setup(). A reference to a std::vector<bool> is passed which
- * is used to decide which file descriptors to close in the child process.
- * While the std::vector<bool> is automatically setup for standard streams
- * developers can change flags to avoid the library closing other file
- * descriptors.
+ * called in the function \a setup is bound to.
*
* On Windows platforms setup() is called in the parent process. A
* reference to a STARTUPINFOA structure is passed as parameter.
*/
- void setup()
- {
- }
-#elif defined(BOOST_POSIX_API)
- void setup(std::vector<bool> &closeflags)
- {
- }
+ boost::function<void ()> setup;
#elif defined(BOOST_WINDOWS_API)
- void setup(STARTUPINFOA &sainfo)
- {
-#if defined(BOOST_MSVC)
- sainfo;
-#endif
- }
+ boost::function<void (STARTUPINFOA&)> setup;
#endif
};
Modified: sandbox/SOC/2010/process/boost/process/detail/basic_status_service.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/basic_status_service.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/basic_status_service.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -109,6 +109,12 @@
std::find(impls_.begin(), impls_.end(), impl);
if (it != impls_.end())
impls_.erase(it);
+#if defined(BOOST_WINDOWS_API)
+ interrupt_work_thread();
+ work_thread_cond_.wait(work_thread_mutex_);
+ impl->clear(handles_);
+ work_thread_cond_.notify_all();
+#endif
impl.reset();
}
Modified: sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -21,10 +21,11 @@
#define BOOST_PROCESS_POSIX_HELPERS_HPP
#include <boost/process/config.hpp>
-#include <boost/process/environment.hpp>
+#include <boost/process/environment.hpp>
#include <string>
-#include <utility>
-#include <cstring>
+#include <utility>
+#include <cstring>
+#include <cstddef>
namespace boost {
namespace process {
@@ -50,19 +51,20 @@
* string of the form var=value. The caller is responsible for
* freeing them.
*/
-inline std::pair<std::size_t, char**> environment_to_envp(const environment &env)
+inline std::pair<std::size_t, char**> environment_to_envp(const environment
+ &env)
{
std::size_t nargs = env.size();
- char **envp = new char*[nargs + 1];
- environment::size_type i = 0;
- for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
- {
- std::string s = it->first + "=" + it->second;
- envp[i] = new char[s.size() + 1];
- std::strncpy(envp[i], s.c_str(), s.size() + 1);
- ++i;
- }
- envp[i] = 0;
+ char **envp = new char*[nargs + 1];
+ environment::size_type i = 0;
+ for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
+ {
+ std::string s = it->first + "=" + it->second;
+ envp[i] = new char[s.size() + 1];
+ std::strncpy(envp[i], s.c_str(), s.size() + 1);
+ ++i;
+ }
+ envp[i] = 0;
return std::pair<std::size_t, char**>(nargs, envp);
}
@@ -86,7 +88,8 @@
std::size_t nargs = args.size();
char **argv = new char*[nargs + 1];
typename Arguments::size_type i = 0;
- for (typename Arguments::const_iterator it = args.begin(); it != args.end(); ++it)
+ for (typename Arguments::const_iterator it = args.begin(); it != args.end();
+ ++it)
{
argv[i] = new char[it->size() + 1];
std::strncpy(argv[i], it->c_str(), it->size() + 1);
Modified: sandbox/SOC/2010/process/boost/process/detail/status_impl.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/status_impl.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/status_impl.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -24,7 +24,9 @@
#if defined(BOOST_POSIX_API)
# include <sys/types.h>
+# include <signal.h>
# include <sys/wait.h>
+# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <windows.h>
#else
@@ -80,6 +82,27 @@
class status_impl
{
public:
+#if defined(BOOST_WINDOWS_API)
+ template <typename Container>
+ void clear(Container &handles)
+ {
+ for (operations_type::iterator it = ops_.begin(); it != ops_.end();
+ ++it)
+ {
+ for (Container::iterator it2 = handles.begin(); it2 !=
+ handles.end(); ++it2)
+ {
+ if (*it2 == it->first)
+ {
+ handles.erase(it2);
+ break;
+ }
+ }
+ CloseHandle(it->first);
+ }
+ }
+#endif
+
int wait(pid_type pid, boost::system::error_code &ec)
{
#if defined(BOOST_POSIX_API)
Modified: sandbox/SOC/2010/process/boost/process/detail/windows_helpers.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/windows_helpers.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/windows_helpers.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -47,7 +47,8 @@
* the environment's content. This string is of the form
* var1=value1\\0var2=value2\\0\\0.
*/
-inline boost::shared_array<char> environment_to_windows_strings(environment &env)
+inline boost::shared_array<char> environment_to_windows_strings(environment
+ &env)
{
boost::shared_array<char> envp;
@@ -59,7 +60,8 @@
else
{
std::string s;
- for (environment::const_iterator it = env.begin(); it != env.end(); ++it)
+ for (environment::const_iterator it = env.begin(); it != env.end();
+ ++it)
{
s += it->first + "=" + it->second;
s.push_back(0);
@@ -88,13 +90,15 @@
* shared_array object to ensure its release at some point.
*/
template <class Arguments>
-inline boost::shared_array<char> collection_to_windows_cmdline(const Arguments &args)
+inline boost::shared_array<char> collection_to_windows_cmdline(const Arguments
+ &args)
{
typedef std::vector<std::string> arguments_t;
arguments_t args2;
typename Arguments::size_type i = 0;
std::size_t size = 0;
- for (typename Arguments::const_iterator it = args.begin(); it != args.end(); ++it)
+ for (typename Arguments::const_iterator it = args.begin(); it != args.end();
+ ++it)
{
std::string arg = *it;
Modified: sandbox/SOC/2010/process/boost/process/handle.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/handle.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/handle.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -41,8 +41,8 @@
*
* The \a handle class is a RAII model for native handles. This class wraps
* one of such handles grabbing its ownership, and automaticaly closes it
- * upon destruction. It is basically used inside the library to avoid leaking
- * open handles, shall an unexpected execution trace occur.
+ * upon destruction. It is used to avoid leaking open handles, shall an
+ * unexpected execution trace occur.
*/
class handle
{
@@ -79,8 +79,9 @@
* Constructs a handle from a native handle.
*
* This constructor creates a new \a handle object that takes
- * ownership of the given \a native handle. The user must not
- * close \a native on his own during the lifetime of the new object.
+ * ownership of the given \a native handle. If \a close is set to
+ * handle::dont_close the \a native handle is not closed upon destruction.
+ * The user must not close \a native if it is owned by a \a handle object.
* Ownership can be reclaimed using release().
*
* \see release()
Modified: sandbox/SOC/2010/process/boost/process/operations.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/operations.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/operations.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -273,7 +273,8 @@
}
}
- ctx.setup(closeflags);
+ if (ctx.setup)
+ ctx.setup();
for (std::size_t i = 0; i < closeflags.size(); ++i)
{
@@ -316,7 +317,8 @@
startup_info.hStdOutput = handles[stdout_id].child.native();
startup_info.hStdError = handles[stderr_id].child.native();
- ctx.setup(startup_info);
+ if (ctx.setup)
+ ctx.setup(startup_info);
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
@@ -339,7 +341,7 @@
handle hprocess(pi.hProcess);
- if (CloseHandle(pi.hThread) == 0)
+ if (!CloseHandle(pi.hThread))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
std::map<stream_id, handle> parent_ends;
Modified: sandbox/SOC/2010/process/boost/process/pid_type.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/pid_type.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/pid_type.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -37,7 +37,7 @@
*
* Each operating system identifies processes using a specific type.
* The \a pid_type type is used to transparently refer to a process
- * regardless of the operating system in which this class is used.
+ * regardless of the operating system.
*
* This type is guaranteed to be an integral type on all supported
* platforms. On POSIX systems it is defined as pid_t, on Windows systems as
Modified: sandbox/SOC/2010/process/boost/process/process.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/process.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/process.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -27,9 +27,9 @@
# include <sys/types.h>
# include <signal.h>
# include <sys/wait.h>
+# include <errno.h>
#elif defined(BOOST_WINDOWS_API)
# include <boost/process/handle.hpp>
-# include <boost/shared_ptr.hpp>
# include <cstdlib>
# include <windows.h>
#else
@@ -97,7 +97,7 @@
* Forces the termination of the process execution. Some platforms
* allow processes to ignore some external termination notifications
* or to capture them for a proper exit cleanup. You can set the
- * \a force flag to true in them to force their termination regardless
+ * \a force flag to true to force their termination regardless
* of any exit handler.
*
* After this call, accessing this object can be dangerous because the
@@ -154,19 +154,22 @@
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
return status;
#elif defined(BOOST_WINDOWS_API)
- HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE, id_);
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
+ id_);
if (h == NULL)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
{
CloseHandle(h);
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("WaitForSingleObject() failed");
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
+ "WaitForSingleObject() failed");
}
DWORD exit_code;
if (!GetExitCodeProcess(h, &exit_code))
{
CloseHandle(h);
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetExitCodeProcess() failed");
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
+ "GetExitCodeProcess() failed");
}
if (!CloseHandle(h))
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
Modified: sandbox/SOC/2010/process/boost/process/self.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/self.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/self.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -101,7 +101,8 @@
char *ms_environ = GetEnvironmentStrings();
if (!ms_environ)
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetEnvironmentStrings() failed");
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
+ "GetEnvironmentStrings() failed");
try
{
char *env = ms_environ;
@@ -158,7 +159,8 @@
BOOST_ASSERT(MAX_PATH > 0);
char cwd[MAX_PATH];
if (!GetCurrentDirectoryA(sizeof(cwd), cwd))
- BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetCurrentDirectory() failed");
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(
+ "GetCurrentDirectory() failed");
BOOST_ASSERT(cwd[0] != '\0');
return cwd;
#endif
Modified: sandbox/SOC/2010/process/boost/process/stream_behavior.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/stream_behavior.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/stream_behavior.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -135,8 +135,6 @@
* Stream behavior to redirect streams with a named pipe.
*
* A child process will be able to communicate with its parent process.
- * On Windows this stream behavior must be used for asynchronous I/O (as only
- * named pipes support asynchronous I/O on Windows).
*/
class named_pipe
{
@@ -218,7 +216,7 @@
* stream behavior is provided for convenience. It uses the minimum required
* pipe type on a platform in order to be able to use asynchronous I/O.
*/
-#if defined(BOOST_POSIX_API)
+#if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
typedef pipe async_pipe;
#elif defined(BOOST_WINDOWS_API)
class async_pipe
Modified: sandbox/SOC/2010/process/boost/process/stream_type.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/stream_type.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/stream_type.hpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -28,7 +28,7 @@
/**
* Stream type to differentiate between input and output streams.
*
- * On POSIX systems another value unknown_stream is define. It is passed
+ * On POSIX systems another value unknown_stream is defined. It is passed
* to stream behaviors for file descriptors greater than 2.
*/
enum stream_type {
Modified: sandbox/SOC/2010/process/libs/process/doc/asyncio.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/asyncio.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/asyncio.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -5,7 +5,7 @@
[import ../example/async_io.cpp]
[async_io]
-Asynchronous I/O operations are based on Boost.Asio. As _pipe_ is an I/O object it must be initialized with an I/O service object. In order to connect the I/O object to a stream the handle of a stream must also be passed to the constructor of _pipe_.
+Asynchronous I/O operations are based on Boost.Asio. As _pipe_ is an I/O object it must be initialized with an I/O service object. In order to connect the I/O object a handle must also be passed to the constructor of _pipe_.
The _handle_ class is a wrapper for a file descriptor on POSIX and a HANDLE on Windows systems. Boost.Process provides the class to avoid leaking handles as the destructor closes them automatically. As both objects of type _handle_ and _pipe_ own handles _handle_release_ must be called to pass ownership of the native handle from the _handle_ instance to the _pipe_ instance.
Modified: sandbox/SOC/2010/process/libs/process/doc/communication.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/communication.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/communication.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -1,15 +1,11 @@
[section:communicating Communicating with child processes]
-The two most interesting stream behaviors are _behavior_pipe_ and _behavior_named_pipe_. You use them to exchange data between a parent and a child process.
+The most interesting stream behaviors are _behavior_pipe_, _behavior_named_pipe_ and _behavior_async_pipe_. You use them to exchange data between a parent and a child process.
[create_child_context_pipe]
-It depends on the stream behavior classes whether parameters are expected. _behavior_pipe_ requires a parameter as it needs to know whether the pipe will be attached to an input or output stream of the child process.
+If a parent process wants to communicate with a child process the return value of _create_child_ should not be discarded. The return value of type _child_ provides access to the newly created child process. The member function _child_get_handle_ is provided to access the other ends of the child process' standard streams.
-If a parent process wants to communicate with a child process the return value of _create_child_ should not be discarded. The return value of type _child_ provides access to the newly created child process. Among others, the member functions _child_get_stdin_, _child_get_stdout_ and _child_get_stderr_ are provided to access the other ends of the child process' standard streams.
-
-[caution You must not call _child_get_stdin_, _child_get_stdout_ and _child_get_stderr_ if you didn't configure the standard streams to be redirected to the parent process.]
-
-The streams returned by _child_get_stdin_, _child_get_stdout_ and _child_get_stderr_ are used similarly to streams from the C++ standard. The type of the return values is either _pistream_ or _postream_ (depending on whether they are input or output streams). These classes are derived from `std::istream` and `std::ostream` and provide two additional member functions `close()` and `handle()`. The latter member function is used for asynchronous I/O.
+The handles returned by _child_get_handle_ can be used to instantiate _pistream_ or _postream_. These classes are defined to support synchronous I/O. They are derived from `std::istream` and `std::ostream` and provide two additional member functions `close()` and `handle()`. For asynchronous I/O another class called _pipe_ has to be instantiated.
[endsect]
Modified: sandbox/SOC/2010/process/libs/process/doc/context.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/context.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/context.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -7,22 +7,25 @@
[import ../example/create_child_context.cpp]
[create_child_context_configuration]
-In practice you are probably more often using the member variables `context::stdin_behavior`, `context::stdout_behavior` and `context::stderr_behavior`. They are used to configure standard streams for child processes.
+In practice you are probably more often using the member variable `context::streams` which is used to configure child standard streams.
-The type of these three member variables is `boost::shared_ptr<boost::process::behavior::stream>`. _behavior_stream_ is the base class of a small hierarchy of behavior classes. Boost.Process provides the following stream behavior classes:
+The type of `context::streams` is `std::map<stream_id, boost::function<stream_ends (stream_type)> >`. While _stream_id_ is an identifier for a stream the value is a so-called stream behavior. These are functions or function objects which describe how a child stream should be configured. They return a pair of handles - a so-called _stream_ends_ - of which one is used as a child stream and the other possibly to access the child stream from the parent process (it's the other end of a pipe).
+
+Boost.Process provides the following stream behavior classes:
* _behavior_inherit_
* _behavior_close_
* _behavior_pipe_
* _behavior_named_pipe_
-* _behavior_dummy_
+* _behavior_async_pipe_
+* _behavior_null_
-It depends on these classes if and how a standard stream can be used by a child process. As it is a class hierarchy you are free to derive your own classes and [link boost_process.user_guide.user_stream_behaviors define new stream behaviors].
+It depends on these classes if and how a stream can be used by a child process. As `context::streams` is based on `boost::function` you are free to [link boost_process.user_guide.user_stream_behaviors define new stream behaviors].
-By default, standard streams are inherited. If you want to configure standard streams differently create an instance of a stream behavior class and assign it. For convenience all behavior classes provide a _behavior_stream_create_ member function which returns an instance of a stream behavior owned by `boost::shared_ptr`.
+By default, standard streams are inherited. If you want to configure standard streams differently simply assign a stream behavior function.
-[create_child_context_dummy]
+[create_child_context_null]
-In the code above the behavior of the standard output stream is changed. Instead of inheriting the standard output stream data written to it will be discarded. The stream is not closed by _behavior_dummy_ but any data is ignored.
+In the code above the behavior of the standard output stream is changed. Instead of inheriting the standard output stream data written to it will be discarded. The stream is not closed by _behavior_null_ but any data is ignored.
[endsect]
Modified: sandbox/SOC/2010/process/libs/process/doc/future.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/future.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/future.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -17,8 +17,7 @@
int main()
{
boost::process::parent p;
- boost::process::postream &os = p.get_stdin();
- boost::process::pipe write_end(ioservice, os.handle().release());
+ boost::process::pipe write_end(ioservice, p.get_handle(boost::process::stdin_id).release());
boost::asio::async_write(write_end, boost::asio::buffer("Hello, world!"), handler);
ioservice.run();
}
Modified: sandbox/SOC/2010/process/libs/process/doc/introduction.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/introduction.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/introduction.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -5,7 +5,7 @@
* create child processes
* run shell commands
* setup environment variables for child processes
-* setup standard streams for child processes
+* setup standard streams for child processes (and other streams on POSIX platforms)
* communicate with child processes through standard streams (synchronously or asynchronously)
* wait for processes to exit (synchronously or asynchronously)
* terminate processes
Modified: sandbox/SOC/2010/process/libs/process/doc/posix.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/posix.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/posix.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -1,25 +1,23 @@
[section:posix POSIX extensions]
-_context_setup_ is an extension point to setup a child process calling platform specific functions. On POSIX systems _context_setup_ is invoked after _fork_ has been called but before _execve_ is called. _context_setup_ is executed within the child process only.
+`context::setup` is an extension point to setup a child process calling platform specific functions. On POSIX systems `context::setup` is invoked after _fork_ has been called but before _execve_ is called. `context::setup` is executed within the child process only.
-In order to inject code into _context_setup_ a new context class has to be defined and derived from _context_. Then one can call for example _chroot_ to change the root directory of the new process.
+First define a function which configures a new child process. The function could for example call _chroot_ to change the root directory.
[import ../example/chroot_setup.cpp]
-[chroot_setup_context]
+[chroot_setup_function]
-The new `context` class is used like _context_.
+Then bind the function to `context::setup`.
[chroot_setup_main]
-[caution When you override _context_setup_ in a multi-threaded application you must not call any function which is not async-signal-safe. Calling non-async-signal-safe functions between _fork_ and _execve_ is undefined behavior in multi-threaded applications. If you must call non-async-signal-safe functions prior to calling _execve_ (because you want to change the root directory with _chroot_ for example) you must create a singlethreaded wrapper process which can safely call non-async-signal-safe function. For more information have a look at the man page of _fork_.]
+[caution When you use `context::setup` in a multi-threaded application you must not call any function which is not async-signal-safe. Calling non-async-signal-safe functions between _fork_ and _execve_ is undefined behavior in multi-threaded applications. If you must call non-async-signal-safe functions prior to calling _execve_ (because you want to change the root directory with _chroot_ for example) you must create a singlethreaded wrapper process which can safely call non-async-signal-safe function. For more information have a look at the man page of _fork_.]
-As you see in the example above a reference to a `std::vector<bool>` is passed to _context_setup_. The flags are used to configure which file descriptors should be closed before _execve_ is called. The flags at the indexes 0, 1 and 2 are set according to the standard stream behaviors. If the child process should inherit additional file descriptors you can change the flags.
+While not really an extension point it is possible to configure more than the standard streams for child processes on POSIX platforms.
[import ../example/file_descriptors_setup.cpp]
-[file_descriptors_context]
-
-This example uses the D-Bus message bus daemon to write data to the file descriptors 3 and 4. In order to read the data in the parent process those file descriptors not only must not be closed. The parent process must also use stream objects and initialize them with the read ends of the pipes.
-
[file_descriptors_main]
+This example uses the D-Bus message bus daemon to write data to the file descriptors 3 and 4. As on POSIX platforms a child's streams can be identified via integers configuring arbitrary many streams is possible.
+
[endsect]
Modified: sandbox/SOC/2010/process/libs/process/doc/process.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/process.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/process.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -22,22 +22,18 @@
[def _pipe_ [classref boost::process::pipe `pipe`]]
[def _pistream_ [classref boost::process::pistream `pistream`]]
[def _postream_ [classref boost::process::postream `postream`]]
+[def _stream_ends_ [classref boost::process::stream_ends `stream_ends`]]
+[def _stream_id_ [classref boost::process::stream_id `stream_id`]]
[def _status_ [classref boost::process::status `status`]]
-[def _behavior_stream_ [classref boost::process::behavior::stream `behavior::stream`]]
[def _behavior_close_ [classref boost::process::behavior::close `behavior::close`]]
[def _behavior_inherit_ [classref boost::process::behavior::inherit `behavior::inherit`]]
[def _behavior_pipe_ [classref boost::process::behavior::pipe `behavior::pipe`]]
[def _behavior_named_pipe_ [classref boost::process::behavior::named_pipe `behavior::named_pipe`]]
-[def _behavior_dummy_ [classref boost::process::behavior::dummy `behavior::dummy`]]
-[def _behavior_stream_create_ [memberref boost::process::behavior::stream::create `create()`]]
-[def _behavior_stream_get_child_end_ [memberref boost::process::behavior::stream::get_child_end `behavior::stream::get_child_end()`]]
-[def _behavior_stream_get_parent_end_ [memberref boost::process::behavior::stream::get_parent_end `behavior::stream::get_parent_end()`]]
-[def _child_get_stdin_ [memberref boost::process::child::get_stdin `child::get_stdin()`]]
-[def _child_get_stdout_ [memberref boost::process::child::get_stdout `child::get_stdout()`]]
-[def _child_get_stderr_ [memberref boost::process::child::get_stderr `child::get_stderr()`]]
+[def _behavior_async_pipe_ [classref boost::process::behavior::async_pipe `behavior::async_pipe`]]
+[def _behavior_null_ [classref boost::process::behavior::null `behavior::null`]]
+[def _child_get_handle_ [memberref boost::process::child::get_handle `child::get_handle()`]]
[def _child_wait_ [memberref boost::process::process::wait `child::wait()`]]
[def _child_terminate_ [memberref boost::process::process::terminate `child::terminate()`]]
-[def _context_setup_ [memberref boost::process::context::setup `context::setup()`]]
[def _handle_release_ [memberref boost::process::handle::release `handle::release()`]]
[def _status_async_wait_ [memberref boost::process::detail::basic_status::async_wait `status::async_wait()`]]
[def _create_child_ [funcref boost::process::create_child `create_child()`]]
Modified: sandbox/SOC/2010/process/libs/process/doc/userstreambehaviors.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/userstreambehaviors.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/userstreambehaviors.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -2,15 +2,11 @@
When creating a child process its standard streams must be configured. By default, standard streams are inherited. Boost.Process provides various stream behaviors to change the default configuration. However as developers might want to do something else with standard streams it's possible to create new stream behaviors.
-In order to create a new stream behavior a class must be derived from _behavior_stream_. There are two virtual member functions inherited which can be overridden: _behavior_stream_get_child_end_ and _behavior_stream_get_parent_end_. These functions return the stream ends for the child and the parent process. The type of the stream ends is _handle_.
-
The following code defines a stream behavior class `redirect_to` which can be used to redirect streams.
[import ../example/redirect_to.cpp]
[redirect_to_stream]
-[caution When you create a stream behavior like `redirect_to` whose constructor expects a handle as a parameter don't save the handle directly. If an existing handle should be reused it must be duplicated. Stream behavior instances own resources and must not share handles.]
-
The following program uses `redirect_to` to redirect the standard error stream of a child process to its standard output stream.
[redirect_to_main]
Modified: sandbox/SOC/2010/process/libs/process/doc/windows.qbk
==============================================================================
--- sandbox/SOC/2010/process/libs/process/doc/windows.qbk (original)
+++ sandbox/SOC/2010/process/libs/process/doc/windows.qbk 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -1,11 +1,11 @@
[section:windows Windows extensions]
-_context_setup_ can be used to configure a child process using Windows specific options. On Windows a reference to a `STARTUPINFOA` object is passed to _context_setup_. If a new context class is created and derived from _context_ the `STARTUPINFOA` object which is used by Boost.Process to start a new process can be configured.
+`context::setup` can be used to configure a child process using Windows specific options. On Windows a reference to a `STARTUPINFOA` object is passed to `context::setup`.
[import ../example/startupinfo_setup.cpp]
-[startupinfo_setup_context]
+[startupinfo_setup_function]
-The `context` class sets window position and size as a hint. It can be used to lanch Notepad for example.
+Here window position and size are set (as a hint) and Notepad is launched.
[startupinfo_setup_main]
Modified: sandbox/SOC/2010/process/libs/process/example/chroot_setup.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/chroot_setup.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/chroot_setup.cpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -19,25 +19,22 @@
#include <vector>
#include <unistd.h>
-//[chroot_setup_context
-class context : public boost::process::context
+//[chroot_setup_function
+void setup()
{
-public:
- void setup(std::vector<bool> &closeflags)
- {
- chroot("/tmp");
- }
-};
+ chroot("/tmp");
+}
//]
+//[chroot_setup_main
int main()
{
-//[chroot_setup_main
std::string exe = boost::process::find_executable_in_path("hostname");
std::vector<std::string> args;
- context ctx;
+ boost::process::context ctx;
+ ctx.setup = &setup;
boost::process::create_child(exe, args, ctx);
-//]
}
+//]
#endif
Modified: sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/file_descriptors_setup.cpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -20,9 +20,9 @@
#include <vector>
#include <iostream>
+//[file_descriptors_main
int main()
{
-//[file_descriptors_main
std::string exe = boost::process::find_executable_in_path("dbus-daemon");
std::vector<std::string> args = boost::assign::list_of("--fork")
@@ -41,7 +41,7 @@
boost::process::pistream ispid(c.get_handle(4));
std::cout << ispid.rdbuf() << std::endl;
-//]
}
+//]
#endif
Modified: sandbox/SOC/2010/process/libs/process/example/startupinfo_setup.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/startupinfo_setup.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/startupinfo_setup.cpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -18,19 +18,15 @@
#include <string>
#include <vector>
-//[startupinfo_setup_context
-class context : public boost::process::context
+//[startupinfo_setup_function
+void setup(STARTUPINFOA &sainfo)
{
-public:
- void setup(STARTUPINFOA &sainfo)
- {
- sainfo.dwFlags |= STARTF_USEPOSITION | STARTF_USESIZE;
- sainfo.dwX = 0;
- sainfo.dwY = 0;
- sainfo.dwXSize = 640;
- sainfo.dwYSize = 480;
- }
-};
+ sainfo.dwFlags |= STARTF_USEPOSITION | STARTF_USESIZE;
+ sainfo.dwX = 0;
+ sainfo.dwY = 0;
+ sainfo.dwXSize = 640;
+ sainfo.dwYSize = 480;
+}
//]
//[startupinfo_setup_main
@@ -38,7 +34,8 @@
{
std::string exe = boost::process::find_executable_in_path("notepad");
std::vector<std::string> args;
- context ctx;
+ boost::process::context ctx;
+ ctx.setup = &setup;
boost::process::create_child(exe, args, ctx);
}
//]
Modified: sandbox/SOC/2010/process/libs/process/test/child.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/child.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/test/child.cpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -755,18 +755,14 @@
#if defined(BOOST_WINDOWS_API)
STARTUPINFOA sa;
-class context : public bp::context
+void setup(STARTUPINFOA &sainfo)
{
-public:
- void setup(STARTUPINFOA &sainfo)
- {
- sa.dwFlags = sainfo.dwFlags |= STARTF_USEPOSITION | STARTF_USESIZE;
- sa.dwX = sainfo.dwX = 100;
- sa.dwY = sainfo.dwY = 200;
- sa.dwXSize = sainfo.dwXSize = 640;
- sa.dwYSize = sainfo.dwYSize = 480;
- }
-};
+ sa.dwFlags = sainfo.dwFlags |= STARTF_USEPOSITION | STARTF_USESIZE;
+ sa.dwX = sainfo.dwX = 100;
+ sa.dwY = sainfo.dwY = 200;
+ sa.dwXSize = sainfo.dwXSize = 640;
+ sa.dwYSize = sainfo.dwYSize = 480;
+}
BOOST_AUTO_TEST_CASE(test_windows)
{
@@ -775,8 +771,9 @@
std::vector<std::string> args;
args.push_back("windows-print-startupinfo");
- context ctx;
+ bp::context ctx;
ctx.streams[bp::stdout_id] = bpb::pipe();
+ ctx.setup = &setup;
bp::child c = bp::create_child(get_helpers_path(), args, ctx);
Modified: sandbox/SOC/2010/process/libs/process/test/wait.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/test/wait.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/test/wait.cpp 2010-10-06 18:51:47 EDT (Wed, 06 Oct 2010)
@@ -123,6 +123,8 @@
s.async_wait(c1.get_id(), handler);
ioservice.run();
+ ioservice.reset();
+
bp::child c2 = bp::create_child(get_helpers_path(), args);
s.async_wait(c2.get_id(), handler);
ioservice.run();
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk