|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r62640 - in sandbox/SOC/2010/process: boost/process boost/process/detail libs/process/example
From: boris_at_[hidden]
Date: 2010-06-09 03:54:40
Author: bschaeling
Date: 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
New Revision: 62640
URL: http://svn.boost.org/trac/boost/changeset/62640
Log:
Updated entire code base after having introduced new stream behavior classes
Removed:
sandbox/SOC/2010/process/boost/process/detail/helper_functions.hpp
sandbox/SOC/2010/process/boost/process/detail/pipe.hpp
sandbox/SOC/2010/process/boost/process/detail/stream_detail.hpp
sandbox/SOC/2010/process/boost/process/posix_child.hpp
Text files modified:
sandbox/SOC/2010/process/boost/process/all.hpp | 29 +---
sandbox/SOC/2010/process/boost/process/child.hpp | 141 +++++++++++++-------------
sandbox/SOC/2010/process/boost/process/context.hpp | 2
sandbox/SOC/2010/process/boost/process/detail/file_handle.hpp | 136 -------------------------
sandbox/SOC/2010/process/boost/process/detail/posix_helpers.hpp | 109 ++++----------------
sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp | 8
sandbox/SOC/2010/process/boost/process/detail/win32_helpers.hpp | 84 ---------------
sandbox/SOC/2010/process/boost/process/environment.hpp | 2
sandbox/SOC/2010/process/boost/process/operations.hpp | 208 +++++++++++----------------------------
sandbox/SOC/2010/process/boost/process/process.hpp | 30 ++---
sandbox/SOC/2010/process/boost/process/self.hpp | 49 ++++-----
sandbox/SOC/2010/process/boost/process/status.hpp | 4
sandbox/SOC/2010/process/boost/process/stream_behavior.hpp | 91 +++++++++++++----
sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp | 4
14 files changed, 281 insertions(+), 616 deletions(-)
Modified: sandbox/SOC/2010/process/boost/process/all.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/all.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/all.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -14,30 +14,21 @@
* \file boost/process/all.hpp
*
* Convenience header that includes all other Boost.Process public header
- * files. It is important to note that those headers that are specific to
- * a given platform are only included if the library is being used in that
- * same platform.
+ * files.
*/
#ifndef BOOST_PROCESS_ALL_HPP
#define BOOST_PROCESS_ALL_HPP
#include <boost/process/config.hpp>
-
-#if defined(BOOST_POSIX_API)
-#elif defined(BOOST_WINDOWS_API)
-#else
-# error "Unsupported platform."
-#endif
-
-# include <boost/process/child.hpp>
-# include <boost/process/context.hpp>
-# include <boost/process/environment.hpp>
-# include <boost/process/operations.hpp>
-# include <boost/process/pistream.hpp>
-# include <boost/process/postream.hpp>
-# include <boost/process/process.hpp>
-# include <boost/process/status.hpp>
-# include <boost/process/stream_behavior.hpp>
+#include <boost/process/child.hpp>
+#include <boost/process/context.hpp>
+#include <boost/process/environment.hpp>
+#include <boost/process/operations.hpp>
+#include <boost/process/pistream.hpp>
+#include <boost/process/postream.hpp>
+#include <boost/process/process.hpp>
+#include <boost/process/status.hpp>
+#include <boost/process/stream_behavior.hpp>
#endif
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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -45,15 +45,40 @@
namespace process {
/**
- * Generic implementation of the Child concept.
- *
- * The child class implements the Child concept in an operating system
- * agnostic way.
+ * The child class provides access to a child process.
*/
class child : public process
{
public:
/**
+ * 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.
+ *
+ * The \a fhprocess handle represents a handle to the child process.
+ * It is only used on Windows as the implementation of wait() needs a
+ * process handle.
+ */
+ child(id_type id, detail::file_handle &fhstdin, detail::file_handle &fhstdout, detail::file_handle &fhstderr, detail::file_handle fhprocess = detail::file_handle())
+ : process(id)
+#if defined(BOOST_WINDOWS_API)
+ , process_handle_(fhprocess.release(), ::CloseHandle)
+#endif
+ {
+ if (fhstdin.valid())
+ stdin_.reset(new postream(fhstdin));
+ if (fhstdout.valid())
+ stdout_.reset(new pistream(fhstdout));
+ if (fhstderr.valid())
+ stderr_.reset(new pistream(fhstderr));
+ }
+
+ /**
* Gets a reference to the child's standard input stream.
*
* Returns a reference to a postream object that represents the
@@ -89,34 +114,6 @@
return *stderr_;
}
- /**
- * 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.
- *
- * The \a fhprocess handle represents a handle to the child process.
- * It is only used on Windows as the implementation of wait() needs a
- * process handle.
- */
- child(id_type id, detail::file_handle &fhstdin, detail::file_handle &fhstdout, detail::file_handle &fhstderr, detail::file_handle fhprocess = detail::file_handle())
- : process(id)
-#if defined(BOOST_WINDOWS_API)
- ,process_handle_(fhprocess.release(), ::CloseHandle)
-#endif
- {
- if (fhstdin.valid())
- stdin_.reset(new postream(fhstdin));
- if (fhstdout.valid())
- stdout_.reset(new pistream(fhstdout));
- if (fhstderr.valid())
- stderr_.reset(new pistream(fhstderr));
- }
-
private:
/**
* The standard input stream attached to the child process.
@@ -158,6 +155,46 @@
#if defined(BOOST_POSIX_API)
public:
/**
+ * 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));
+ }
+ }
+ }
+
+ /**
* Gets a reference to the child's input stream \a desc.
*
* Returns a reference to a postream object that represents one of
@@ -209,46 +246,6 @@
}
}
- /**
- * 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.
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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -38,7 +38,7 @@
boost::shared_ptr<stream_behavior> stderr_behavior;
std::string process_name;
std::string work_dir;
- environment_t environment;
+ environment environment;
/**
* Constructs a process 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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -32,9 +32,6 @@
#endif
#include <boost/assert.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/throw_exception.hpp>
-#include <stdio.h>
namespace boost {
namespace process {
@@ -108,6 +105,8 @@
file_handle(handle_type h)
: handle_(h)
{
+ // Boris: I wonder why this assert existed before (also in
+ // previous Boost.Process versions).
// BOOST_ASSERT(handle_ != invalid_value());
}
@@ -232,67 +231,6 @@
::close(handle_);
handle_ = invalid_value();
}
-
- /**
- * Changes the native file handle to the given one.
- *
- * Given a new native file handle \a h, this operation assigns this
- * handle to the current object, closing its old native file handle.
- * In other words, it first calls dup2() to remap the old handle to
- * the new one and then closes the old handle.
- *
- * If \a h is open, it is automatically closed by dup2().
- *
- * This operation is only available in POSIX systems.
- *
- * \pre The file handle is valid.
- * \pre The native file handle \a h is valid; i.e., it must be
- * closeable.
- * \post The file handle's native file handle is \a h.
- * \throw boost::system::system_error If the internal remapping
- * operation fails.
- */
- void posix_remap(handle_type &h)
- {
- BOOST_ASSERT(valid());
-
- if (::dup2(handle_, h) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: dup2(2) failed"));
-
- if (::close(handle_) == -1)
- ::close(h);
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: close(2) failed"));
-
- if(::dup2(handle_,h) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_remap: dup2(2) failed"));
-
- handle_ = h;
- }
-
- /**
- * Duplicates an open native file handle.
- *
- * Given a native file handle \a h1, this routine duplicates it so
- * that it ends up being identified by the native file handle \a h2
- * and returns a new \a file_handle owning \a h2.
- *
- * This operation is only available in POSIX systems.
- *
- * \pre The native file handle \a h1 is open.
- * \pre The native file handle \a h2 is valid (non-negative).
- * \post The native file handle \a h1 is closed.
- * \post The native file handle \a h2 is the same as the old \a h1
- * from the operating system's point of view.
- * \return A new \a file_handle object that owns \a h2.
- * \throw boost::system::system_error If dup2() fails.
- */
- static file_handle duplicate(int h1, int h2)
- {
- if (::dup2(h1, h2) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::file_handle::posix_dup: dup2(2) failed"));
-
- return file_handle(h2);
- }
#endif
#if defined(BOOST_WINDOWS_API) || defined(BOOST_PROCESS_DOXYGEN)
@@ -312,76 +250,6 @@
::CloseHandle(handle_);
handle_ = invalid_value();
}
-
- /**
- * Duplicates the \a h native file handle.
- *
- * Given a native file handle \a h, this routine constructs a new
- * \a file_handle object that owns a new duplicate of \a h. The
- * duplicate's inheritable flag is set to the value of \a inheritable.
- *
- * This operation is only available in Windows systems.
- *
- * \pre The native file handle \a h is valid.
- * \return A file handle owning a duplicate of \a h.
- * \throw boost::system::system_error If DuplicateHandle() fails.
- */
- static file_handle win32_dup(HANDLE h, bool inheritable)
- {
- HANDLE h2;
-
- if (::DuplicateHandle(::GetCurrentProcess(), h, ::GetCurrentProcess(), &h2, 0, inheritable ? TRUE : FALSE, DUPLICATE_SAME_ACCESS) == 0)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_dup: DuplicateHandle failed"));
-
- return file_handle(h2);
- }
-
- /**
- * Creates a new duplicate of a standard file handle.
- *
- * Constructs a new \a file_handle object that owns a duplicate of a
- * standard file handle. The \a d parameter specifies which standard
- * file handle to duplicate and can be one of \a STD_INPUT_HANDLE,
- * \a STD_OUTPUT_HANDLE or \a STD_ERROR_HANDLE. The duplicate's
- * inheritable flag is set to the value of \a inheritable.
- *
- * This operation is only available in Windows systems.
- *
- * \pre \a d refers to one of the standard handles as described above.
- * \return A file handle owning a duplicate of the standard handle
- * referred to by \a d.
- * \throw boost::system::system_error If GetStdHandle() or
- * DuplicateHandle() fails.
- */
- static file_handle win32_dup_std(DWORD d, bool inheritable)
- {
- BOOST_ASSERT(d == STD_INPUT_HANDLE || d == STD_OUTPUT_HANDLE || d == STD_ERROR_HANDLE);
- HANDLE h = ::GetStdHandle(d);
- if (h == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_std:GetStdHandle failed"));
- file_handle dh = win32_dup(h, inheritable);
- return dh;
- }
-
- /**
- * Changes the file handle's inheritable flag.
- *
- * Changes the file handle's inheritable flag to \a i. It is not
- * necessary for the file handle's flag to be different than \a i.
- *
- * This operation is only available in Windows systems.
- *
- * \pre The file handle is valid.
- * \post The native file handle's inheritable flag is set to \a i.
- * \throw boost::system::system_error If the property change fails.
- */
- void win32_set_inheritable(bool i)
- {
- BOOST_ASSERT(valid());
-
- if (!::SetHandleInformation(handle_, HANDLE_FLAG_INHERIT, i ? HANDLE_FLAG_INHERIT : 0))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::file_handle::win32_set_inheritable: SetHandleInformation failed"));
- }
#endif
private:
Deleted: sandbox/SOC/2010/process/boost/process/detail/helper_functions.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/helper_functions.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,34 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-/**
- * \file boost/process/detail/helper_functions.hpp
- *
- * Includes the declaration of helper functions for the operations.
- * It's for internal purposes.
- *
- */
-
-#include <boost/process/config.hpp>
-
-#ifndef BOOST_PROCESS_HELPER_FUNCTIONS_HPP
-#define BOOST_PROCESS_HELPER_FUNCTIONS_HPP
-
-namespace boost {
-namespace process {
-namespace detail {
-
-}
-}
-}
-
-#endif
Deleted: sandbox/SOC/2010/process/boost/process/detail/pipe.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/pipe.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,188 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-/**
- * \file boost/process/detail/pipe.hpp
- *
- * Includes the declaration of the pipe class. This file is for
- * internal usage only and must not be included by the library user.
- */
-
-#ifndef BOOST_PROCESS_DETAIL_PIPE_HPP
-#define BOOST_PROCESS_DETAIL_PIPE_HPP
-
-#include <boost/process/config.hpp>
-
-#if defined(BOOST_POSIX_API)
-# include <unistd.h>
-# include <cerrno>
-#elif defined(BOOST_WINDOWS_API)
-# if defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE)
-# include <boost/lexical_cast.hpp>
-# include <string>
-# endif
-# include <windows.h>
-#else
-# error "Unsupported platform."
-#endif
-
-#include <boost/process/detail/file_handle.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/throw_exception.hpp>
-
-namespace boost {
-namespace process {
-namespace detail {
-
-/**
- * Simple RAII model for anonymous pipes.
- *
- * The pipe class is a simple RAII model for anonymous pipes. It
- * provides a portable constructor that allocates a new %pipe and creates
- * a pipe object that owns the two file handles associated to it: the
- * read end and the write end.
- *
- * These handles can be retrieved for modification according to
- * file_handle semantics. Optionally, their ownership can be transferred
- * to external \a file_handle objects which comes handy when the two
- * ends need to be used in different places (i.e. after a POSIX fork()
- * system call).
- *
- * Pipes can be copied following the same semantics as file handles.
- * In other words, copying a %pipe object invalidates the source one.
- *
- * \see file_handle
- */
-class pipe
-{
-public:
- /**
- * Creates a new %pipe.
- *
- * The default pipe constructor allocates a new anonymous %pipe
- * and assigns its ownership to the created pipe object. On Windows
- * when the macro BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE is defined
- * a named pipe is created. This is required if asynchronous I/O
- * should be used as asynchronous I/O is only supported by named
- * pipes on Windows.
- *
- * \throw boost::system::system_error If the anonymous %pipe
- * creation fails.
- */
- pipe()
- {
- file_handle::handle_type hs[2];
-
-#if defined(BOOST_POSIX_API)
- if (::pipe(hs) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::pipe::pipe: 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 defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE)
- static unsigned int nextid = 0;
- std::string pipe = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++);
- hs[0] = ::CreateNamedPipeA(pipe.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
- if (hs[0] == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateNamedPipe failed"));
- hs[1] = ::CreateFileA(pipe.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (hs[1] == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateFile failed"));
-
- OVERLAPPED overlapped;
- ZeroMemory(&overlapped, sizeof(overlapped));
- overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!overlapped.hEvent)
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateEvent failed"));
- BOOL b = ::ConnectNamedPipe(hs[0], &overlapped);
- if (!b)
- {
- if (::GetLastError() == ERROR_IO_PENDING)
- {
- if (::WaitForSingleObject(overlapped.hEvent, INFINITE)
- == WAIT_FAILED)
- {
- ::CloseHandle(overlapped.hEvent);
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: WaitForSingleObject failed"));
- }
- }
- else if (::GetLastError() != ERROR_PIPE_CONNECTED)
- {
- ::CloseHandle(overlapped.hEvent);
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: ConnectNamedPipe failed"));
- }
- }
- ::CloseHandle(overlapped.hEvent);
-# else
- if (!::CreatePipe(&hs[0], &hs[1], &sa, 0))
- boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreatePipe failed"));
-# endif
-#endif
-
- read_end_ = file_handle(hs[0]);
- write_end_ = file_handle(hs[1]);
- }
-
- /**
- * Returns the %pipe's read end file handle.
- *
- * Obtains a reference to the %pipe's read end file handle. Care
- * should be taken to not duplicate the returned object if ownership
- * shall remain to the %pipe.
- *
- * Duplicating the returned object invalidates its corresponding file
- * handle in the %pipe.
- *
- * \return A reference to the %pipe's read end file handle.
- */
- file_handle &rend()
- {
- return read_end_;
- }
-
- /**
- * Returns the %pipe's write end file handle.
- *
- * Obtains a reference to the %pipe's write end file handle. Care
- * should be taken to not duplicate the returned object if ownership
- * shall remain to the %pipe.
- *
- * Duplicating the returned object invalidates its corresponding file
- * handle in the %pipe.
- *
- * \return A reference to the %pipe's write end file handle.
- */
- file_handle &wend()
- {
- return write_end_;
- }
-
-private:
- /**
- * The %pipe's read end file handle.
- */
- file_handle read_end_;
-
- /**
- * The %pipe's write end file handle.
- */
- file_handle write_end_;
-};
-
-}
-}
-}
-
-#endif
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-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -13,90 +13,24 @@
/**
* \file boost/process/detail/posix_helper.hpp
*
- * Includes the declaration of helper functions for the operations in a posix
- * system. It's for internal purposes.
+ * Includes the declaration of helper functions for the operations in a POSIX
+ * system.
*
*/
-#include <boost/process/config.hpp>
-
-#if defined(BOOST_POSIX_API)
-# include <unistd.h>
-# include <sys/stat.h>
-# include <fcntl.h>
-# include <stdio.h>
-#endif
-
-#include <boost/optional.hpp>
-#include <boost/process/stream_behavior.hpp>
-#include <boost/process/detail/stream_detail.hpp>
-#include <map>
-#include <string.h>
-
#ifndef BOOST_PROCESS_POSIX_HELPERS_HPP
#define BOOST_PROCESS_POSIX_HELPERS_HPP
+#include <boost/process/config.hpp>
+#include <boost/process/environment.hpp>
+#include <string>
+#include <utility>
+#include <cstring>
+
namespace boost {
namespace process {
namespace detail {
-/*
- * This is the declaration of configure_stream function.
- * This function, given an stream_detail inherit from the current process
- * father, configure the stream.
- *
- * Note that this function is meant to be called on a brand-new child.
- *
- */
-inline configure_child_posix_stream(stream_detail &s)
-{
- switch (s.behavior)
- {
- case dummy:
- {
- std::string null_file;
- if(s.stream_type == stdin_type)
- null_file = "/dev/null";
- else
- null_file = "/dev/zero";
-
- int fd;
- if(s.stream_type == stdin_type)
- fd = ::open(null_file.c_str(), O_RDONLY);
- else
- fd = ::open(null_file.c_str(), O_WRONLY);
-
- if (fd == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::detail::setup_input: open(2) of " + s.object.file_ + " failed"));
-
- s.object.handle_ = file_handle(fd);
- s.object.handle_.posix_remap(s.stream_handle);
- s.object.handle_.release();
- break;
- }
- case closed:
- ::close(s.stream_handle);
- break;
- case inherit:
- //do nothing since is default?
- break;
- case capture:
- if (s.stream_type == stdin_type)
- {
- s.object.pipe_.wend().close();
- s.object.pipe_.rend().posix_remap(s.stream_handle);
- }
- else
- {
- s.object.pipe_.rend().close();
- s.object.pipe_.wend().posix_remap(s.stream_handle);
- }
- break;
- default:
- BOOST_ASSERT(false);
- }
-}
-
/**
* Converts an environment to a char** table as used by execve().
*
@@ -111,20 +45,21 @@
* the environment's content. Each array entry is a
* NULL-terminated string of the form var=value.
*/
-inline char **environment_to_envp(environment_t env)
+inline char **environment_to_envp(const environment &env)
{
- char **envp = new char*[env.size() + 1];
+ char **envp = new char*[env.size() + 1];
- unsigned int i = 0;
- for (environment_t::const_iterator it = env.begin(); it != env.end(); ++it)
- {
- std::string s = (*it).first + "=" + (*it).second;
- envp[i] = new char[s.size() + 1];
- ::strncpy(envp[i], s.c_str(), s.size() + 1);
- ++i;
- }
- envp[i] = 0;
- return envp;
+ 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 envp;
}
/**
@@ -152,7 +87,7 @@
for (typename Arguments::const_iterator it = args.begin(); it != args.end(); ++it)
{
argv[i] = new char[it->size() + 1];
- ::strncpy(argv[i], it->c_str(), it->size() + 1);
+ std::strncpy(argv[i], it->c_str(), it->size() + 1);
++i;
}
argv[nargs] = 0;
Deleted: sandbox/SOC/2010/process/boost/process/detail/stream_detail.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/stream_detail.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,124 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-/**
- * \file boost/process/detail/stream_detail.hpp
- *
- * Includes the declaration of the stream_detail struct.
- * It's for internal purposes
- *
- */
-
-#ifndef BOOST_PROCESS_STREAM_DETAIL_HPP
-#define BOOST_PROCESS_STREAM_DETAIL_HPP
-
-#include <boost/process/config.hpp>
-#include <boost/process/stream_behavior.hpp>
-#include <boost/process/detail/file_handle.hpp>
-#include <boost/process/detail/pipe.hpp>
-#include <boost/optional.hpp>
-#include <map>
-
-namespace boost {
-namespace process {
-namespace detail {
-
-/*
- * This is the declaration of stream_object.
- * It represents all types that can be assign of an stream object
- * representation. For example, it can point to another stream or
- * to a pipe.
- */
-struct stream_object
-{
- int desc_to;
- std::string file_;
- file_handle handle_;
- pipe pipe_;
-};
-
-/*
- * This defines the std_stream_type enum.
- * It lists all possible std stream types.
- */
-enum std_stream_type { stdin_type = 0, stdout_type = 1, stderr_type = 2 };
-
-/*
- * This is the declaration of a stream detail.
- * A stream detail contains all details from one standard stream
- * (in, out or err) that are needed for adjust it
- * when a new process is created.
- *
- * stream_end: The adress of the stream
- * stream_type: Defines if the stream is a stdin, out or error.
- * behavior: The behavior this stream will assume
- * object: The object required to this behavior (see stream_object above)
- *
- */
-struct stream_detail
-{
-#if defined(BOOST_POSIX_API)
- int stream_handle;
-#elif defined(BOOST_WINDOWS_API)
- DWORD stream_handle;
-#endif
-
- struct stream_object object;
- std_stream_type stream_type;
- stream_behavior behavior;
-
- stream_detail(std_stream_type st)
- {
- stream_type = st;
- object.pipe_ = pipe();
- switch(st)
- {
- case stdin_type:
- {
-#if defined(BOOST_POSIX_API)
- stream_handle = STDIN_FILENO;
-#elif defined(BOOST_WINDOWS_API)
- stream_handle = STD_INPUT_HANDLE;
-#endif
- break;
- }
- case stdout_type:
- {
-#if defined(BOOST_POSIX_API)
- stream_handle = STDOUT_FILENO;
-#elif defined(BOOST_WINDOWS_API)
- stream_handle = STD_OUTPUT_HANDLE;
-#endif
- break;
- }
- case stderr_type:
- {
-#if defined(BOOST_POSIX_API)
- stream_handle = STDERR_FILENO;
-#elif defined(BOOST_WINDOWS_API)
- stream_handle = STD_ERROR_HANDLE;
-#endif
- break;
- }
- default:
- {
- BOOST_ASSERT(false);
- }
- }
- }
-};
-
-}
-}
-}
-
-#endif
Modified: sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/detail/systembuf.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -23,12 +23,12 @@
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
-# include <sys/types.h>
-# include <unistd.h>
+# include <sys/types.h>
+# include <unistd.h>
#elif defined(BOOST_WINDOWS_API)
-# include <windows.h>
+# include <windows.h>
#else
-# error "Unsupported platform."
+# error "Unsupported platform."
#endif
#include <boost/noncopyable.hpp>
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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -14,7 +14,7 @@
* \file boost/process/detail/helper_functions.hpp
*
* Includes the declaration of helper functions for the operations in a win32
- * system. It's for internal purposes.
+ * system.
*
*/
@@ -22,19 +22,9 @@
#define BOOST_PROCESS_WIN32_HELPERS_HPP
#include <boost/process/config.hpp>
-#include <boost/process/child.hpp>
-#include <boost/process/detail/file_handle.hpp>
-#include <boost/process/detail/stream_detail.hpp>
-#include <boost/process/detail/pipe.hpp>
-#include <boost/scoped_ptr.hpp>
#include <boost/shared_array.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/assert.hpp>
-#include <boost/system/system_error.hpp>
-#include <boost/throw_exception.hpp>
-#include <vector>
-#include <map>
#include <string>
+#include <vector>
#include <cstddef>
#include <string.h>
#include <windows.h>
@@ -55,7 +45,7 @@
* the environment's content. This string is of the form
* var1=value1\\0var2=value2\\0\\0.
*/
-inline boost::shared_array<char>environment_to_win32_strings(environment_t &env)
+inline boost::shared_array<char> environment_to_win32_strings(environment &env)
{
boost::shared_array<char> envp;
@@ -67,8 +57,7 @@
else
{
std::string s;
- for (environment_t::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);
@@ -136,71 +125,6 @@
return cmdline;
}
-/*
- * This function configures the std stream of the new process.
- * 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;
-
- switch (sd.behavior)
- {
- case close:
- {
- return_handle = file_handle();
- break;
- }
- case inherit:
- {
- return_handle = file_handle::win32_dup_std(sd.stream_handle, true);
- break;
- }
- case mute:
- {
- HANDLE h;
- if(sd.stream_type == stdin_type)
- {
- h = ::CreateFileA("NUL", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- }
- else
- {
- h = ::CreateFileA("NUL", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- }
- if (h == INVALID_HANDLE_VALUE)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateFile failed"));
- return_handle = file_handle(h);
- break;
- }
-
- case capture:
- {
- if(sd.stream_type == stdin_type)
- {
- sd.object.pipe_.rend().win32_set_inheritable(true);
- return_handle = sd.object.pipe_.rend();
- }
- else
- {
- sd.object.pipe_.wend().win32_set_inheritable(true);
- return_handle = sd.object.pipe_.wend();
- }
-
- break;
- }
-
- default:
- {
- BOOST_ASSERT(false);
- }
- }
-
- return return_handle;
-}
-*/
-
}
}
}
Modified: sandbox/SOC/2010/process/boost/process/environment.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/environment.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/environment.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -43,7 +43,7 @@
* This is provided for-free by the map container used to implement this
* type, and this behavior is required by Windows systems.
*/
-typedef std::map<std::string, std::string> environment_t;
+typedef std::map<std::string, std::string> environment;
}
}
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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -42,7 +42,6 @@
#include <boost/process/stream_behavior.hpp>
#include <boost/process/status.hpp>
#include <boost/process/detail/file_handle.hpp>
-#include <boost/process/detail/stream_detail.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include <boost/system/system_error.hpp>
@@ -128,7 +127,7 @@
#endif
if (result.empty())
- boost::throw_exception(boost::filesystem::filesystem_error("boost::process::find_executable_in_path: file not found", file, boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory)));
+ boost::throw_exception(boost::filesystem::filesystem_error(BOOST_PROCESS_SOURCE_LOCATION "file not found", file, boost::system::errc::make_error_code(boost::system::errc::no_such_file_or_directory)));
return result;
}
@@ -176,22 +175,8 @@
template <class Arguments>
inline child create_child(const std::string &executable, Arguments args, context ctx = context())
{
- /*
- * BEHAVIOR | BEFORE fork/CreateProcess | AFTER fork/CreateProcess
- * ---------+----------------------------------+---------------------------------
- * inherit | Windows: duplicate handle and |
- * | save it in STARTUPINFO |
- * capture | POSIX: create pipe | POSIX: use one end to initialize
- * | Windows: create pipe and save | child process object
- * | one end in STARTUPINFO |
- * mute | POSIX: open file |
- * | Windows: open file and save |
- * | handle in STARTUPINFO |
- * close | | POSIX: close explicitly
- */
-
- std::string p_name = ctx.process_name.empty() ? executable : ctx.process_name;
- args.insert(args.begin(), p_name);
+ 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();
@@ -201,11 +186,56 @@
if (pid == 0)
{
+#if defined(F_MAXFD)
+ int maxdescs = ::fcntl(-1, F_MAXFD, 0);
+ if (maxdescs == -1)
+ maxdescs = ::sysconf(_SC_OPEN_MAX);
+#else
+ int maxdescs = ::sysconf(_SC_OPEN_MAX);
+#endif
+ if (maxdescs == -1)
+ maxdescs = 1024;
+ try
+ {
+ boost::scoped_array<bool> closeflags(new bool[maxdescs]);
+ for (int i = 0; i < maxdescs; ++i)
+ closeflags[i] = true;
+
+ // setup_input(infoin, closeflags.get(), maxdescs);
+ // setup_output(infoout, closeflags.get(), maxdescs);
+
+ int stdin_fd = ctx.stdin_behavior->get_child_end();
+ if (stdin_fd != -1 && stdin_fd < maxdescs)
+ closeflags[stdin_fd] = false;
+
+ int stdout_fd = ctx.stdout_behavior->get_child_end();
+ if (stdout_fd != -1 && stdout_fd < maxdescs)
+ closeflags[stdout_fd] = false;
+
+ int stderr_fd = ctx.stderr_behavior->get_child_end();
+ if (stderr_fd != -1 && stderr_fd < maxdescs)
+ closeflags[stderr_fd] = false;
+
+ for (int i = 0; i < maxdescs; ++i)
+ {
+ if (closeflags[i])
+ ::close(i);
+ }
+
+ // setup();
+ }
+ catch (const boost::system::system_error &e)
+ {
+ ::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
+ ::write(STDERR_FILENO, "\n", 1);
+ std::exit(EXIT_FAILURE);
+ }
+
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");
+ boost::system::system_error e(boost::system::error_code(errno, boost::system::get_system_category()), BOOST_PROCESS_SOURCE_LOCATION "execve(2) failed");
for (std::size_t i = 0; i < argcv.first; ++i)
delete[] argcv.second[i];
@@ -217,11 +247,20 @@
::write(STDERR_FILENO, e.what(), std::strlen(e.what()));
::write(STDERR_FILENO, "\n", 1);
+ // TODO: Use return values which is less likely used by the
+ // program which should have been started.
std::exit(EXIT_FAILURE);
}
BOOST_ASSERT(pid > 0);
+ if (ctx.stdin_behavior->get_child_end() != -1)
+ ::close(ctx.stdin_behavior->get_child_end());
+ if (ctx.stdout_behavior->get_child_end() != -1)
+ ::close(ctx.stdout_behavior->get_child_end());
+ if (ctx.stderr_behavior->get_child_end() != -1)
+ ::close(ctx.stderr_behavior->get_child_end());
+
return child(pid,
detail::file_handle(ctx.stdin_behavior->get_parent_end()),
detail::file_handle(ctx.stdout_behavior->get_parent_end()),
@@ -260,137 +299,6 @@
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.
- detail::stream_detail stdin_stream(detail::stdin_type),
- stdout_stream(detail::stdout_type),
- stderr_stream(detail::stderr_type);
-
- stdin_stream.behavior = ctx.stdin_behavior;
- stdout_stream.behavior = ctx.stdout_behavior;
- stderr_stream.behavior = ctx.stderr_behavior;
-
- //adjust process name
- 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::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::create_child: fork(2) failed"));
-
- if (pid == 0)
- {
- // child process
- detail::configure_posix_stream(stdin_stream);
- detail::configure_posix_stream(stdout_stream);
- detail::configure_posix_stream(stderr_stream);
-
- 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);
-
- // error handling in case execve() failed
- 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);
-
- //adjust father pipes
- if(ctx.stdin_behavior == capture)
- {
- stdin_stream.object.pipe_.rend().close();
- fhstdin = stdin_stream.object.pipe_.wend().release();
- BOOST_ASSERT(fhstdin.valid());
- }
-
- if(ctx.stdout_behavior == capture)
- {
- stdout_stream.object.pipe_.wend().close();
- fhstdout = stdout_stream.object.pipe_.wend().release();
- BOOST_ASSERT(fhstdout.valid());
- }
-
- if(ctx.stderr_behavior == capture)
- {
- stderr_stream.object.pipe_.wend().close();
- fhstderr = stderr_stream.object.pipe_.wend().release();
- BOOST_ASSERT(fhstderr.valid());
- }
-
- return child(pid, fhstdin, fhstdout, fhstderr);
-#elif defined(BOOST_WINDOWS_API)
- //Set up the pipes when needed for the current process.
- if (stdin_stream.behavior == capture)
- fhstdin = stdin_stream.object.pipe_.wend();
- if (stdout_stream.behavior == capture)
- fhstdout = stdout_stream.object.pipe_.rend();
- if (stderr_stream.behavior == capture)
- fhstderr = stderr_stream.object.pipe_.rend();
-
- //define startup info from the new child
- STARTUPINFOA startup_info;
- ::ZeroMemory(&startup_info, sizeof(startup_info));
- startup_info.cb = sizeof(startup_info);
-
- startup_info.dwFlags |= STARTF_USESTDHANDLES;
-
- //configure std stream info for the child
- //TODO: Find a better way to do it,without file handle
- detail::file_handle fh;
-
- fh = configure_win32_stream(stdin_stream);
- if(fh.valid())
- startup_info.hStdInput = fh.get();
-
- fh = configure_win32_stream(stdout_stream);
- if(fh.valid())
- startup_info.hStdOutput = fh.get();
-
- fh = configure_win32_stream(stderr_stream);
- if(fh.valid())
- startup_info.hStdError = fh.get();
-
- //define process info and create it
- 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);
-
- //create the process
- if (::CreateProcessA(exe.get(), cmdline.get(), NULL, NULL, TRUE, 0, envstrs.get(), workdir.get(), &startup_info, &pi) == 0)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::detail::win32_start: CreateProcess failed"));
-
- if (!::CloseHandle(pi.hThread))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::launch: CloseHandle failed"));
-
- return child(pi.dwProcessId, fhstdin, fhstdout, fhstderr, detail::file_handle(pi.hProcess));
-#endif
- */
}
inline child create_child(const std::string &executable, context ctx = context())
Deleted: sandbox/SOC/2010/process/boost/process/posix_child.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/posix_child.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
+++ (empty file)
@@ -1,181 +0,0 @@
-//
-// Boost.Process
-// ~~~~~~~~~~~~~
-//
-// Copyright (c) 2006, 2007 Julio M. Merino Vidal
-// Copyright (c) 2008, 2009 Boris Schaeling
-// Copyright (c) 2010 Felipe Tanus, Boris Schaeling
-//
-// Distributed under the Boost Software License, Version 1.0. (See accompanying
-// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-//
-
-/**
- * \file boost/process/posix_child.hpp
- *
- * Includes the declaration of the posix_child class.
- */
-
-#ifndef BOOST_PROCESS_POSIX_CHILD_HPP
-#define BOOST_PROCESS_POSIX_CHILD_HPP
-
-#include <boost/process/child.hpp>
-#include <boost/process/pistream.hpp>
-#include <boost/process/postream.hpp>
-#include <boost/process/detail/pipe.hpp>
-#include <boost/process/detail/posix_ops.hpp>
-#include <boost/process/detail/stream_info.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/assert.hpp>
-#include <map>
-#include <unistd.h>
-
-namespace boost {
-namespace process {
-
-/**
- * POSIX implementation of the Child concept.
- *
- * The posix_child class implements the Child concept in a POSIX
- * operating system.
- *
- * A POSIX child differs from a regular child (represented by a
- * child object) in that it supports more than three communication
- * channels with its parent. These channels are identified by regular
- * file descriptors (integers).
- *
- * This class is built on top of the generic child so as to allow its
- * trivial adoption. When a program is changed to use the POSIX-specific
- * context (posix_context), it will most certainly need to migrate its
- * use of the child class to posix_child. Doing so is only a matter of
- * redefining the appropriate object and later using the required extra
- * features: there should be no need to modify the existing code (e.g.
- * method calls) in any other way.
- */
-class posix_child : public child
-{
-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;
- }
- }
-
- /**
- * Constructs a new POSIX child object representing a just
- * spawned child process.
- *
- * Creates a new child object that represents the just spawned process
- * \a id.
- *
- * 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.
- */
- posix_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/process.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/process.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/process.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -22,13 +22,13 @@
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
-# include <cerrno>
-# include <signal.h>
+# include <cerrno>
+# include <signal.h>
#elif defined(BOOST_WINDOWS_API)
-# include <cstdlib>
-# include <windows.h>
+# include <cstdlib>
+# include <windows.h>
#else
-# error "Unsupported platform."
+# error "Unsupported platform."
#endif
#include <boost/process/status.hpp>
@@ -40,10 +40,8 @@
namespace process {
/**
- * Generic implementation of the Process concept.
- *
- * The process class implements the Process concept in an operating system
- * agnostic way.
+ * The process class provides access to an unrelated process (a process
+ * which is neither a child process nor a parent process nor self).
*/
class process
{
@@ -105,19 +103,19 @@
{
#if defined(BOOST_POSIX_API)
if (::kill(id_, force ? SIGKILL : SIGTERM) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::process::terminate: kill(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("kill(2) failed");
#elif defined(BOOST_WINDOWS_API)
HANDLE h = ::OpenProcess(PROCESS_TERMINATE, FALSE, id_);
if (h == NULL)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: OpenProcess failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("OpenProcess() failed");
if (!::TerminateProcess(h, EXIT_FAILURE))
{
::CloseHandle(h);
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: TerminateProcess failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("TerminateProcess() failed");
}
if (!::CloseHandle(h))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::terminate: CloseHandle failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
#endif
}
@@ -137,14 +135,14 @@
#if defined(BOOST_POSIX_API)
int s;
if (::waitpid(get_id(), &s, 0) == -1)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::process::wait: waitpid(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("waitpid(2) failed");
return status(s);
#elif defined(BOOST_WINDOWS_API)
// TODO
// Boris: Where do we get the process handle from? It should be possible to fetch it
// as we do have the process ID saved in the member variable id_. I guess
// there must be a Windows API function to get a process handle from a process ID?
- if (::WaitForSingleObject(process_handle_.get(),INFINITE) == WAIT_FAILED)
+ if (::WaitForSingleObject(process_handle_.get(), INFINITE) == WAIT_FAILED)
{
// TODO
// Boris: What should happen if WaitForSingleObject() fails? Under what
@@ -154,7 +152,7 @@
}
DWORD code;
if (!::GetExitCodeProcess(process_handle_.get(), &code))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::process::wait: GetExitCodeProcess failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetExitCodeProcess() failed");
return status(code);
#endif
}
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-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -22,16 +22,16 @@
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
-# include <boost/scoped_array.hpp>
-# include <cerrno>
-# include <unistd.h>
-# if defined(__APPLE__)
-# include <crt_externs.h>
-# endif
+# include <boost/scoped_array.hpp>
+# include <cerrno>
+# include <unistd.h>
+# if defined(__APPLE__)
+# include <crt_externs.h>
+# endif
#elif defined(BOOST_WINDOWS_API)
-# include <windows.h>
+# include <windows.h>
#else
-# error "Unsupported platform."
+# error "Unsupported platform."
#endif
#include <boost/process/process.hpp>
@@ -53,9 +53,7 @@
namespace process {
/**
- * Generic implementation of the Process concept.
- *
- * The self singleton provides access to the current process.
+ * The self class provides access to the process itself.
*/
class self : public process, boost::noncopyable
{
@@ -77,33 +75,32 @@
* Returns the current process' environment variables. Modifying the
* returned object has no effect on the current environment.
*/
- static environment_t get_environment()
+ static environment get_environment()
{
- environment_t e;
+ environment e;
#if defined(BOOST_POSIX_API)
-# if defined(__APPLE__)
+# if defined(__APPLE__)
char **env = *_NSGetEnviron();
-# else
+# else
char **env = ::environ;
-# endif
+# endif
while (*env)
{
std::string s = *env;
std::string::size_type pos = s.find('=');
- e.insert(boost::process::environment_t::value_type(s.substr(0, pos), s.substr(pos + 1)));
+ e.insert(boost::process::environment::value_type(s.substr(0, pos), s.substr(pos + 1)));
++env;
}
-
#elif defined(BOOST_WINDOWS_API)
-# ifdef GetEnvironmentStrings
-# undef GetEnvironmentStrings
-# endif
+# ifdef GetEnvironmentStrings
+# undef GetEnvironmentStrings
+# endif
char *ms_environ = ::GetEnvironmentStrings();
if (!ms_environ)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::self::get_environment: GetEnvironmentStrings failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("GetEnvironmentStrings() failed");
try
{
char *env = ms_environ;
@@ -111,7 +108,7 @@
{
std::string s = env;
std::string::size_type pos = s.find('=');
- e.insert(boost::process::environment_t::value_type(s.substr(0, pos), s.substr(pos + 1)));
+ e.insert(boost::process::environment::value_type(s.substr(0, pos), s.substr(pos + 1)));
env += s.size() + 1;
}
}
@@ -132,20 +129,20 @@
errno = 0;
long size = ::pathconf(".", _PC_PATH_MAX);
if (size == -1 && errno)
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::self::get_work_dir: pathconf(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("pathconf(2) failed");
else if (size == -1)
size = BOOST_PROCESS_POSIX_PATH_MAX;
BOOST_ASSERT(size > 0);
boost::scoped_array<char> cwd(new char[size]);
if (!::getcwd(cwd.get(), size))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(errno, boost::system::get_system_category()), "boost::process::self::get_work_dir: getcwd(2) failed"));
+ BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("getcwd(2) failed");
BOOST_ASSERT(cwd[0] != '\0');
return cwd.get();
#elif defined(BOOST_WINDOWS_API)
BOOST_ASSERT(MAX_PATH > 0);
char cwd[MAX_PATH];
if (!::GetCurrentDirectoryA(sizeof(cwd), cwd))
- boost::throw_exception(boost::system::system_error(boost::system::error_code(::GetLastError(), boost::system::get_system_category()), "boost::process::self::get_work_dir: 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/status.hpp
==============================================================================
--- sandbox/SOC/2010/process/boost/process/status.hpp (original)
+++ sandbox/SOC/2010/process/boost/process/status.hpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -22,10 +22,10 @@
#include <boost/process/config.hpp>
#if defined(BOOST_POSIX_API)
-# include <sys/wait.h>
+# include <sys/wait.h>
#elif defined(BOOST_WINDOWS_API)
#else
-# error "Unsupported platform."
+# error "Unsupported platform."
#endif
#include <boost/assert.hpp>
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-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -13,7 +13,7 @@
/**
* \file boost/process/stream_behavior.hpp
*
- * Includes the declaration of the stream_behavior enumeration.
+ * Includes the declaration of the stream_behavior classes.
*
*/
@@ -35,18 +35,26 @@
namespace boost {
namespace process {
+/*
+ * BEHAVIOR | BEFORE fork/CreateProcess | AFTER fork/CreateProcess
+ * ---------+----------------------------------+---------------------------------
+ * close | | POSIX: close explicitly
+ * inherit | Windows: duplicate handle and |
+ * | save it in STARTUPINFO |
+ * capture | POSIX: create pipe | POSIX: use one end to initialize
+ * | Windows: create pipe and save | child process object
+ * | one end in STARTUPINFO | Windows: same
+ * mute | POSIX: open file |
+ * | Windows: open file and save |
+ * | handle in STARTUPINFO |
+ */
+
/**
+ * Stream behaviors are used to configure streams of a child process.
*
- * Stream behaviors to define how standard streams are passed to a child process.
- *
- * inherit: A stream is inherited from its parent process.
- * capture: A stream is redirected to its parent process (anonymous pipe).
- * mute: A stream is redirected to /dev/null, /dev/zero or NUL.
- * close: A stream is closed.
- *
+ * The class stream_behavior is the base class all other stream behavior
+ * classes must be derived from.
*/
-// enum stream_behavior { inherit, capture, mute, close };
-
class stream_behavior
{
public:
@@ -75,8 +83,19 @@
}
};
+/**
+ * Stream behavior to close streams of a child process.
+ *
+ * A child process will not be able to use its streams.
+ */
typedef stream_behavior close;
+/**
+ * Stream behavior to make a child process inherit streams.
+ *
+ * A child process will use the very same streams the current
+ * process uses.
+ */
class inherit : public stream_behavior
{
public:
@@ -98,6 +117,12 @@
native_type child_end_;
};
+/**
+ * Stream behavior to redirect streams with a pipe.
+ *
+ * A child process will be able to communicate with the current
+ * process.
+ */
class capture : public stream_behavior
{
public:
@@ -141,50 +166,66 @@
native_type parent_end_;
};
+/**
+ * Stream behavior to redirect streams with a named pipe.
+ *
+ * A child process will be able to communicate with the current
+ * process. On Windows this stream behavior must be used for
+ * asynchronous I/O (as only named pipes support asynchronous I/O
+ * on Windows).
+ */
class capture_with_named_pipe : public stream_behavior
{
public:
enum stream_type { input_stream, output_stream };
- capture_with_named_pipe(stream_type stream)
+ capture_with_named_pipe(stream_type stream, std::string name = "")
{
native_type natives[2];
#if defined(BOOST_POSIX_API)
+ if (name.empty())
+ // TODO: Generate unique filename.
+ name = "/tmp/fifo.1";
+
// 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)
+ if (::mkfifo(name.c_str(), 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);
+ child_end_ = ::open(name.c_str(), O_RDONLY);
if (child_end_ == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
- parent_end_ = ::open("/tmp/fifo.1", O_WRONLY);
+ parent_end_ = ::open(name.c_str(), O_WRONLY);
if (parent_end_ == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
}
else
{
- child_end_ = ::open("/tmp/fifo.1", O_WRONLY);
+ child_end_ = ::open(name.c_str(), O_WRONLY);
if (child_end_ == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
- parent_end_ = ::open("/tmp/fifo.1", O_RDONLY);
+ parent_end_ = ::open(name.c_str(), O_RDONLY);
if (parent_end_ == -1)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("open(2) failed");
}
#elif defined(BOOST_WINDOWS_API)
+ if (name.empty())
+ {
+ // TODO: Make this thread-safe (create unique filename differently).
+ static unsigned int nextid = 0;
+ name = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++);
+ }
+
// 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);
+ natives[0] = ::CreateNamedPipeA(name.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);
+ natives[1] = ::CreateFileA(name.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");
@@ -235,6 +276,12 @@
native_type parent_end_;
};
+/**
+ * Stream behavior to mute streams.
+ *
+ * A child process will be able to use streams. But data written to an
+ * output stream is discarded and data read from an input stream is 0.
+ */
class mute : public stream_behavior
{
public:
@@ -249,7 +296,7 @@
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)
+ if (child_end_ == INVALID_HANDLE_VALUE)
BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CreateFile() failed");
#endif
}
Modified: sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp
==============================================================================
--- sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp (original)
+++ sandbox/SOC/2010/process/libs/process/example/child_stdin.cpp 2010-06-09 03:54:33 EDT (Wed, 09 Jun 2010)
@@ -10,7 +10,7 @@
// 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 <string>
#include <iostream>
@@ -20,7 +20,7 @@
{
std::string exe = find_executable_in_path("ftp");
context ctx;
- ctx.stdin_behavior = capture;
+ ctx.stdin_behavior = boost::make_shared<capture>(capture(capture::input_stream));
child c = create_child(exe, ctx);
postream &os = c.get_stdin();
os << "quit" << 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