Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r62520 - in sandbox/SOC/2010/process: boost/process boost/process/detail libs/process/example
From: boris_at_[hidden]
Date: 2010-06-07 16:43:14


Author: bschaeling
Date: 2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
New Revision: 62520
URL: http://svn.boost.org/trac/boost/changeset/62520

Log:
Made stream behaviors types (instead of enum values)
Text files modified:
   sandbox/SOC/2010/process/boost/process/child.hpp | 127 +++++++++++++++++++++
   sandbox/SOC/2010/process/boost/process/config.hpp | 29 ++++
   sandbox/SOC/2010/process/boost/process/context.hpp | 28 ++--
   sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp | 10
   sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp | 2
   sandbox/SOC/2010/process/boost/process/operations.hpp | 98 ++++++++++++++--
   sandbox/SOC/2010/process/boost/process/stream_behavior.hpp | 228 +++++++++++++++++++++++++++++++++++++++
   sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp | 9 +
   8 files changed, 490 insertions(+), 41 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-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,10 +22,15 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
+# include <boost/process/detail/pipe.hpp>
+# include <boost/process/detail/posix_ops.hpp>
+# include <boost/process/detail/stream_info.hpp>
+# include <map>
+# include <unistd.h>
 #elif defined(BOOST_WINDOWS_API)
-# include <windows.h>
+# include <windows.h>
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/process/process.hpp>
@@ -149,6 +154,124 @@
      */
     boost::shared_ptr<void> process_handle_;
 #endif
+
+#if defined(BOOST_POSIX_API)
+public:
+ /**
+ * Gets a reference to the child's input stream \a desc.
+ *
+ * Returns a reference to a postream object that represents one of
+ * the multiple input communication channels with the child process.
+ * The channel is identified by \a desc as seen from the child's
+ * point of view. The parent can use the returned stream to send
+ * data to the child.
+ *
+ * Giving this function the STDIN_FILENO constant (defined in
+ * unistd.h) is a synonym for the get_stdin() call inherited from
+ * child.
+ */
+ postream &get_input(int desc) const
+ {
+ if (desc == STDIN_FILENO)
+ return posix_child::get_stdin();
+ else
+ {
+ input_map_t::const_iterator it = input_map_.find(desc);
+ BOOST_ASSERT(it != input_map_.end());
+ return *it->second;
+ }
+ }
+
+ /**
+ * Gets a reference to the child's output stream \a desc.
+ *
+ * Returns a reference to a pistream object that represents one of
+ * the multiple output communication channels with the child process.
+ * The channel is identified by \a desc as seen from the child's
+ * point of view. The parent can use the returned stream to retrieve
+ * data from the child.
+ *
+ * Giving this function the STDOUT_FILENO or STDERR_FILENO constants
+ * (both defined in unistd.h) are synonyms for the get_stdout() and
+ * get_stderr() calls inherited from child, respectively.
+ */
+ pistream &get_output(int desc) const
+ {
+ if (desc == STDOUT_FILENO)
+ return posix_child::get_stdout();
+ else if (desc == STDERR_FILENO)
+ return posix_child::get_stderr();
+ else
+ {
+ output_map_t::const_iterator it = output_map_.find(desc);
+ BOOST_ASSERT(it != output_map_.end());
+ return *it->second;
+ }
+ }
+
+ /**
+ * Creates a new child object on a POSIX platform.
+ *
+ * The \a infoin and \a infoout maps contain the pipes used to handle
+ * the redirections of the child process; at the moment, no other
+ * stream_info types are supported. If the launcher was asked to
+ * redirect any of the three standard flows, their pipes must be
+ * present in these maps.
+ */
+ child(id_type id, detail::info_map &infoin, detail::info_map &infoout)
+ : child(id,
+ detail::posix_info_locate_pipe(infoin, STDIN_FILENO, false),
+ detail::posix_info_locate_pipe(infoout, STDOUT_FILENO, true),
+ detail::posix_info_locate_pipe(infoout, STDERR_FILENO, true))
+ {
+ for (detail::info_map::iterator it = infoin.begin();
+ it != infoin.end(); ++it)
+ {
+ detail::stream_info &si = it->second;
+ if (si.type_ == detail::stream_info::use_pipe)
+ {
+ BOOST_ASSERT(si.pipe_->wend().valid());
+ boost::shared_ptr<postream> st(new postream(si.pipe_->wend()));
+ input_map_.insert(input_map_t::value_type(it->first, st));
+ }
+ }
+
+ for (detail::info_map::iterator it = infoout.begin();
+ it != infoout.end(); ++it)
+ {
+ detail::stream_info &si = it->second;
+ if (si.type_ == detail::stream_info::use_pipe)
+ {
+ BOOST_ASSERT(si.pipe_->rend().valid());
+ boost::shared_ptr<pistream> st(new pistream(si.pipe_->rend()));
+ output_map_.insert(output_map_t::value_type(it->first, st));
+ }
+ }
+ }
+
+private:
+ /**
+ * Maps child's file descriptors to postream objects.
+ */
+ typedef std::map<int, boost::shared_ptr<postream> > input_map_t;
+
+ /**
+ * Contains all relationships between child's input file
+ * descriptors and their corresponding postream objects.
+ */
+ input_map_t input_map_;
+
+ /**
+ * Maps child's file descriptors to pistream objects.
+ */
+ typedef std::map<int, boost::shared_ptr<pistream> > output_map_t;
+
+ /**
+ * Contains all relationships between child's output file
+ * descriptors and their corresponding pistream objects.
+ */
+ output_map_t output_map_;
+#endif
 };
 
 /**

Modified: sandbox/SOC/2010/process/boost/process/config.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/config.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/config.hpp 2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -3,6 +3,7 @@
 // ~~~~~~~~~~~~~
 //
 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
+// Copyright (c) 2008 Ilya Sokolov
 // Copyright (c) 2008, 2009 Boris Schaeling
 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
 //
@@ -22,9 +23,16 @@
 
 #include <boost/config.hpp>
 #include <boost/system/config.hpp>
+#include <boost/preprocessor/stringize.hpp>
+#include <boost/system/system_error.hpp>
+#include <boost/throw_exception.hpp>
+
+#if defined(BOOST_WINDOWS_API)
+# include <windows.h>
+#endif
 
 #if defined(BOOST_POSIX_API) || defined(BOOST_PROCESS_DOXYGEN)
-# if !defined(BOOST_PROCESS_POSIX_PATH_MAX)
+# if !defined(BOOST_PROCESS_POSIX_PATH_MAX)
 /**
  * The macro BOOST_PROCESS_POSIX_PATH_MAX is set to a positive integer
  * value which specifies the system's maximal supported path length.
@@ -34,8 +42,23 @@
  * constructor of context tries to find out the maximal supported path
  * length but uses BOOST_PROCESS_POSIX_PATH_MAX if it fails.
  */
-# define BOOST_PROCESS_POSIX_PATH_MAX 259
-# endif
+# define BOOST_PROCESS_POSIX_PATH_MAX 259
+# endif
 #endif
 
+#define BOOST_PROCESS_SOURCE_LOCATION \
+ "in file '" __FILE__ "', line " BOOST_PP_STRINGIZE(__LINE__) ": "
+
+#if defined(BOOST_POSIX_API)
+# define BOOST_PROCESS_LAST_ERROR errno
+#elif defined(BOOST_WINDOWS_API)
+# define BOOST_PROCESS_LAST_ERROR ::GetLastError()
+#endif
+
+#define BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR(what) \
+ boost::throw_exception(boost::system::system_error( \
+ boost::system::error_code(BOOST_PROCESS_LAST_ERROR, \
+ boost::system::get_system_category()), \
+ BOOST_PROCESS_SOURCE_LOCATION what))
+
 #endif

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-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,6 +22,8 @@
 #include <boost/process/stream_behavior.hpp>
 #include <boost/process/environment.hpp>
 #include <boost/process/self.hpp>
+#include <boost/shared_ptr.hpp>
+#include <boost/make_shared.hpp>
 
 namespace boost {
 namespace process {
@@ -31,9 +33,9 @@
  */
 struct context
 {
- stream_behavior stdin_behavior;
- stream_behavior stdout_behavior;
- stream_behavior stderr_behavior;
+ boost::shared_ptr<stream_behavior> stdin_behavior;
+ boost::shared_ptr<stream_behavior> stdout_behavior;
+ boost::shared_ptr<stream_behavior> stderr_behavior;
     std::string process_name;
     std::string work_dir;
     environment_t environment;
@@ -45,23 +47,21 @@
      * and environment variables.
      */
     context()
- : stdin_behavior(inherit),
- stdout_behavior(inherit),
- stderr_behavior(inherit),
+#if defined(BOOST_POSIX_API)
+ : stdin_behavior(boost::make_shared<inherit>(inherit(STDIN_FILENO))),
+ stdout_behavior(boost::make_shared<inherit>(inherit(STDOUT_FILENO))),
+ stderr_behavior(boost::make_shared<inherit>(inherit(STDERR_FILENO))),
+#elif defined(BOOST_WINDOWS_API)
+ : stdin_behavior(boost::make_shared<inherit>(inherit(::GetStdHandle(STD_INPUT_HANDLE)))),
+ stdout_behavior(boost::make_shared<inherit>(inherit(::GetStdHandle(STD_OUTPUT_HANDLE)))),
+ stderr_behavior(boost::make_shared<inherit>(inherit(::GetStdHandle(STD_ERROR_HANDLE)))),
+#endif
         work_dir(self::get_work_dir()),
         environment(self::get_environment())
     {
     }
 };
 
-/**
- * Default context object.
- *
- * The default context object is used when child processes are created
- * without defining a context explicitly.
- */
-const context default_context;
-
 }
 }
 

Modified: sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp 2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -23,12 +23,12 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-# include <cerrno>
-# include <unistd.h>
+# include <cerrno>
+# include <unistd.h>
 #elif defined(BOOST_WINDOWS_API)
-# include <windows.h>
+# include <windows.h>
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/assert.hpp>
@@ -108,7 +108,7 @@
     file_handle(handle_type h)
         : handle_(h)
     {
- BOOST_ASSERT(handle_ != invalid_value());
+ // BOOST_ASSERT(handle_ != invalid_value());
     }
 
     /**

Modified: sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp 2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -141,6 +141,7 @@
  * It recieves stream_detail from that stream and return a file_handle
  * that contains the handle to the stream.
  */
+/*
 inline file_handle configure_win32_stream(stream_detail &sd)
 {
     file_handle return_handle;
@@ -198,6 +199,7 @@
 
     return return_handle;
 }
+*/
 
 }
 }

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-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,19 +22,19 @@
 #include <boost/process/config.hpp>
 
 #if defined(BOOST_POSIX_API)
-# include <boost/process/detail/posix_helpers.hpp>
-# include <stdlib.h>
-# include <unistd.h>
-# if defined(__CYGWIN__)
-# include <boost/scoped_array.hpp>
-# include <sys/cygwin.h>
-# endif
+# include <boost/process/detail/posix_helpers.hpp>
+# include <stdlib.h>
+# include <unistd.h>
+# if defined(__CYGWIN__)
+# include <boost/scoped_array.hpp>
+# include <sys/cygwin.h>
+# endif
 #elif defined(BOOST_WINDOWS_API)
-# include <boost/process/detail/win32_helpers.hpp>
-# include <boost/algorithm/string/predicate.hpp>
-# include <windows.h>
+# include <boost/process/detail/win32_helpers.hpp>
+# include <boost/algorithm/string/predicate.hpp>
+# include <windows.h>
 #else
-# error "Unsupported platform."
+# error "Unsupported platform."
 #endif
 
 #include <boost/process/child.hpp>
@@ -174,7 +174,7 @@
  * \return A handle to the new child process.
  */
 template <class Arguments>
-inline child create_child(const std::string &executable, Arguments args, context ctx = default_context)
+inline child create_child(const std::string &executable, Arguments args, context ctx = context())
 {
     /*
      * BEHAVIOR | BEFORE fork/CreateProcess | AFTER fork/CreateProcess
@@ -190,6 +190,77 @@
      * close | | POSIX: close explicitly
      */
 
+ std::string p_name = ctx.process_name.empty() ? executable : ctx.process_name;
+ args.insert(args.begin(), p_name);
+
+#if defined(BOOST_POSIX_API)
+ child::id_type pid = ::fork();
+
+ if (pid == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("fork(2) failed");
+
+ if (pid == 0)
+ {
+ std::pair<std::size_t, char**> argcv = detail::collection_to_posix_argv(args);
+ char **envp = detail::environment_to_envp(ctx.environment);
+ ::execve(executable.c_str(), argcv.second, envp);
+
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::create_child: execve(2) failed");
+
+ for (std::size_t i = 0; i < argcv.first; ++i)
+ delete[] argcv.second[i];
+ delete[] argcv.second;
+
+ for (std::size_t i = 0; i < env.size(); ++i)
+ delete[] envp[i];
+ delete[] envp;
+
+ ::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
+ ::write(STDERR_FILENO, "\n", 1);
+ std::exit(EXIT_FAILURE);
+ }
+
+ BOOST_ASSERT(pid > 0);
+
+ return child(pid,
+ detail::file_handle(ctx.stdin_behavior->get_parent_end()),
+ detail::file_handle(ctx.stdout_behavior->get_parent_end()),
+ detail::file_handle(ctx.stderr_behavior->get_parent_end()));
+#elif defined(BOOST_WINDOWS_API)
+ STARTUPINFOA startup_info;
+ ::ZeroMemory(&startup_info, sizeof(startup_info));
+ startup_info.cb = sizeof(startup_info);
+ startup_info.dwFlags |= STARTF_USESTDHANDLES;
+ startup_info.hStdInput = ctx.stdin_behavior->get_child_end();
+ startup_info.hStdOutput = ctx.stdout_behavior->get_child_end();
+ startup_info.hStdError = ctx.stderr_behavior->get_child_end();
+
+ PROCESS_INFORMATION pi;
+ ::ZeroMemory(&pi, sizeof(pi));
+
+ boost::shared_array<char> cmdline = detail::collection_to_win32_cmdline(args);
+
+ boost::scoped_array<char> exe(new char[executable.size() + 1]);
+ ::strcpy_s(exe.get(), executable.size() + 1, executable.c_str());
+
+ boost::scoped_array<char> workdir(new char[ctx.work_dir.size() + 1]);
+ ::strcpy_s(workdir.get(), ctx.work_dir.size() + 1, ctx.work_dir.c_str());
+
+ boost::shared_array<char> envstrs = detail::environment_to_win32_strings(ctx.environment);
+
+ if (::CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0, envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateProcess() failed");
+
+ if (!::CloseHandle(pi.hThread))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
+
+ return child(pi.dwProcessId,
+ detail::file_handle(ctx.stdin_behavior->get_parent_end()),
+ detail::file_handle(ctx.stdout_behavior->get_parent_end()),
+ detail::file_handle(ctx.stderr_behavior->get_parent_end()),
+ detail::file_handle(pi.hProcess));
+#endif
+ /*
     detail::file_handle fhstdin, fhstdout, fhstderr;
 
     //start structures that represents a std stream.
@@ -319,9 +390,10 @@
 
     return child(pi.dwProcessId, fhstdin, fhstdout, fhstderr, detail::file_handle(pi.hProcess));
 #endif
+ */
 }
 
-inline child create_child(const std::string &executable, context ctx = default_context)
+inline child create_child(const std::string &executable, context ctx = context())
 {
     return create_child(executable, std::vector<std::string>(), ctx);
 }

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-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -22,6 +22,16 @@
 
 #include <boost/process/config.hpp>
 
+#if defined(BOOST_POSIX_API)
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <unistd.h>
+#elif defined(BOOST_WINDOWS_API)
+# include <boost/lexical_cast.hpp>
+# include <string>
+# include <windows.h>
+#endif
+
 namespace boost {
 namespace process {
 
@@ -35,7 +45,223 @@
  * close: A stream is closed.
  *
  */
-enum stream_behavior { inherit, capture, mute, close };
+// enum stream_behavior { inherit, capture, mute, close };
+
+class stream_behavior
+{
+public:
+#if defined(BOOST_POSIX_API)
+ typedef int native_type;
+#elif defined(BOOST_WINDOWS_API)
+ typedef HANDLE native_type;
+#endif
+
+ virtual native_type get_child_end() const
+ {
+#if defined(BOOST_POSIX_API)
+ return -1;
+#elif defined(BOOST_WINDOWS_API)
+ return INVALID_HANDLE_VALUE;
+#endif
+ }
+
+ virtual native_type get_parent_end() const
+ {
+#if defined(BOOST_POSIX_API)
+ return -1;
+#elif defined(BOOST_WINDOWS_API)
+ return INVALID_HANDLE_VALUE;
+#endif
+ }
+};
+
+typedef stream_behavior close;
+
+class inherit : public stream_behavior
+{
+public:
+ inherit(native_type child_end)
+ : child_end_(child_end)
+ {
+#if defined(BOOST_WINDOWS_API)
+ if (!::DuplicateHandle(::GetCurrentProcess(), child_end_, ::GetCurrentProcess(), &child_end_, 0, TRUE, DUPLICATE_SAME_ACCESS))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("DuplicateHandle() failed");
+#endif
+ }
+
+ native_type get_child_end() const
+ {
+ return child_end_;
+ }
+
+private:
+ native_type child_end_;
+};
+
+class capture : public stream_behavior
+{
+public:
+ enum stream_type { input_stream, output_stream };
+
+ capture(stream_type stream)
+ {
+ native_type natives[2];
+#if defined(BOOST_POSIX_API)
+ if (::pipe(natives) == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pipe(2) failed");
+#elif defined(BOOST_WINDOWS_API)
+ SECURITY_ATTRIBUTES sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+ if (!::CreatePipe(&natives[0], &natives[1], &sa, 0))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreatePipe() failed");
+#endif
+ child_end_ = natives[(stream == input_stream) ? 0 : 1];
+ parent_end_ = natives[(stream == input_stream) ? 1 : 0];
+#if defined(BOOST_WINDOWS_API)
+ if (!::SetHandleInformation(child_end_, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetHandleInformation() failed");
+#endif
+ }
+
+ native_type get_child_end() const
+ {
+ return child_end_;
+ }
+
+ native_type get_parent_end() const
+ {
+ return parent_end_;
+ }
+
+private:
+ native_type child_end_;
+ native_type parent_end_;
+};
+
+class capture_with_named_pipe : public stream_behavior
+{
+public:
+ enum stream_type { input_stream, output_stream };
+
+ capture_with_named_pipe(stream_type stream)
+ {
+ native_type natives[2];
+#if defined(BOOST_POSIX_API)
+ // TODO: Use RAII to close HANDLEs if an exception is thrown.
+ if (::mkfifo("/tmp/fifo.1", S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("mkfifo(3) failed");
+ if (stream == input_stream)
+ {
+ child_end_ = ::open("/tmp/fifo.1", O_RDONLY);
+ if (child_end_ == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
+ parent_end_ = ::open("/tmp/fifo.1", O_WRONLY);
+ if (parent_end_ == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
+ }
+ else
+ {
+ child_end_ = ::open("/tmp/fifo.1", O_WRONLY);
+ if (child_end_ == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
+ parent_end_ = ::open("/tmp/fifo.1", O_RDONLY);
+ if (parent_end_ == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
+ }
+#elif defined(BOOST_WINDOWS_API)
+ // TODO: Use RAII to close HANDLEs if an exception is thrown.
+ SECURITY_ATTRIBUTES sa;
+ ZeroMemory(&sa, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+ // TODO: Make this thread-safe (create unique filename differently).
+ static unsigned int nextid = 0;
+ std::string pipe = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++);
+ natives[0] = ::CreateNamedPipeA(pipe.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
+ if (natives[0] == INVALID_HANDLE_VALUE)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateNamedPipe() failed");
+ natives[1] = ::CreateFileA(pipe.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+ if (natives[1] == INVALID_HANDLE_VALUE)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
+
+ OVERLAPPED overlapped;
+ ZeroMemory(&overlapped, sizeof(overlapped));
+ overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!overlapped.hEvent)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateEvent() failed");
+ BOOL b = ::ConnectNamedPipe(natives[0], &overlapped);
+ if (!b)
+ {
+ if (::GetLastError() == ERROR_IO_PENDING)
+ {
+ if (::WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_FAILED)
+ {
+ ::CloseHandle(overlapped.hEvent);
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("WaitForSingleObject() failed");
+ }
+ }
+ else if (::GetLastError() != ERROR_PIPE_CONNECTED)
+ {
+ ::CloseHandle(overlapped.hEvent);
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("ConnectNamedPipe() failed");
+ }
+ }
+ ::CloseHandle(overlapped.hEvent);
+#endif
+ child_end_ = natives[(stream == input_stream) ? 0 : 1];
+ parent_end_ = natives[(stream == input_stream) ? 1 : 0];
+#if defined(BOOST_WINDOWS_API)
+ if (!::SetHandleInformation(child_end_, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT))
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("SetHandleInformation() failed");
+#endif
+ }
+
+ native_type get_child_end() const
+ {
+ return child_end_;
+ }
+
+ native_type get_parent_end() const
+ {
+ return parent_end_;
+ }
+
+private:
+ native_type child_end_;
+ native_type parent_end_;
+};
+
+class mute : public stream_behavior
+{
+public:
+ enum stream_type { input_stream, output_stream };
+
+ mute(stream_type stream)
+ {
+#if defined(BOOST_POSIX_API)
+ std::string filename = (stream == input_stream) ? "/dev/zero" : "/dev/null";
+ child_end_ = ::open(filename.c_str(), O_RDONLY);
+ if (child_end_ == -1)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
+#elif defined(BOOST_WINDOWS_API)
+ child_end_ = ::CreateFileA("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (child_end_ == INVALID_HANDLE_VALUE)
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
+#endif
+ }
+
+ native_type get_child_end() const
+ {
+ return child_end_;
+ }
+
+private:
+ native_type child_end_;
+};
 
 }
 }

Modified: sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/child_stdout.cpp 2010-06-07 16:43:12 EDT (Mon, 07 Jun 2010)
@@ -10,7 +10,8 @@
 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 //
 
-#include <boost/all/process.hpp>
+#include <boost/process/all.hpp>
+#include <boost/make_shared.hpp>
 #include <string>
 #include <iostream>
 
@@ -20,8 +21,10 @@
 {
     std::string exe = find_executable_in_path("hostname");
     context ctx;
- ctx.stdout_behavior = capture;
+ ctx.stdout_behavior = boost::make_shared<capture>(capture(capture::output_stream));
     child c = create_child(exe, ctx);
     pistream &is = c.get_stdout();
- std::cout << is.rdbuf();
+ std::string hostname;
+ is >> hostname;
+ std::cout << hostname << std::endl;
 }


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