00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00019 #ifndef BOOST_PROCESS_DETAIL_PIPE_HPP
00020 #define BOOST_PROCESS_DETAIL_PIPE_HPP
00021
00022 #include <boost/process/config.hpp>
00023
00024 #if defined(BOOST_POSIX_API)
00025 # include <unistd.h>
00026 # include <cerrno>
00027 #elif defined(BOOST_WINDOWS_API)
00028 # if defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE)
00029 # include <boost/lexical_cast.hpp>
00030 # include <string>
00031 # endif
00032 # include <windows.h>
00033 #else
00034 # error "Unsupported platform."
00035 #endif
00036
00037 #include <boost/process/detail/file_handle.hpp>
00038 #include <boost/system/system_error.hpp>
00039 #include <boost/throw_exception.hpp>
00040
00041 namespace boost {
00042 namespace process {
00043 namespace detail {
00044
00064 class pipe
00065 {
00066 public:
00080 pipe()
00081 {
00082 file_handle::handle_type hs[2];
00083
00084 #if defined(BOOST_POSIX_API)
00085 if (::pipe(hs) == -1)
00086 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"));
00087 #elif defined(BOOST_WINDOWS_API)
00088 SECURITY_ATTRIBUTES sa;
00089 ZeroMemory(&sa, sizeof(sa));
00090 sa.nLength = sizeof(sa);
00091 sa.lpSecurityDescriptor = NULL;
00092 sa.bInheritHandle = FALSE;
00093
00094 # if defined(BOOST_PROCESS_WINDOWS_USE_NAMED_PIPE)
00095 static unsigned int nextid = 0;
00096 std::string pipe = "\\\\.\\pipe\\boost_process_" + boost::lexical_cast<std::string>(::GetCurrentProcessId()) + "_" + boost::lexical_cast<std::string>(nextid++);
00097 hs[0] = ::CreateNamedPipeA(pipe.c_str(), PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, 0, 1, 8192, 8192, 0, &sa);
00098 if (hs[0] == INVALID_HANDLE_VALUE)
00099 boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateNamedPipe failed"));
00100 hs[1] = ::CreateFileA(pipe.c_str(), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
00101 if (hs[1] == INVALID_HANDLE_VALUE)
00102 boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateFile failed"));
00103
00104 OVERLAPPED overlapped;
00105 ZeroMemory(&overlapped, sizeof(overlapped));
00106 overlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00107 if (!overlapped.hEvent)
00108 boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreateEvent failed"));
00109 BOOL b = ::ConnectNamedPipe(hs[0], &overlapped);
00110 if (!b)
00111 {
00112 if (::GetLastError() == ERROR_IO_PENDING)
00113 {
00114 if (::WaitForSingleObject(overlapped.hEvent, INFINITE) == WAIT_FAILED)
00115 {
00116 ::CloseHandle(overlapped.hEvent);
00117 boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: WaitForSingleObject failed"));
00118 }
00119 }
00120 else if (::GetLastError() != ERROR_PIPE_CONNECTED)
00121 {
00122 ::CloseHandle(overlapped.hEvent);
00123 boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: ConnectNamedPipe failed"));
00124 }
00125 }
00126 ::CloseHandle(overlapped.hEvent);
00127 # else
00128 if (!::CreatePipe(&hs[0], &hs[1], &sa, 0))
00129 boost::throw_exception(boost::system::system_error(::GetLastError(), boost::system::system_category, "boost::process::detail::pipe::pipe: CreatePipe failed"));
00130 # endif
00131 #endif
00132
00133 read_end_ = file_handle(hs[0]);
00134 write_end_ = file_handle(hs[1]);
00135 }
00136
00149 file_handle &rend()
00150 {
00151 return read_end_;
00152 }
00153
00166 file_handle &wend()
00167 {
00168 return write_end_;
00169 }
00170
00171 private:
00175 file_handle read_end_;
00176
00180 file_handle write_end_;
00181 };
00182
00183 }
00184 }
00185 }
00186
00187 #endif