ian@0
|
1 //
|
ian@0
|
2 // Boost.Process
|
ian@0
|
3 // ~~~~~~~~~~~~~
|
ian@0
|
4 //
|
ian@0
|
5 // Copyright (c) 2006, 2007 Julio M. Merino Vidal
|
ian@0
|
6 // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling
|
ian@0
|
7 // Copyright (c) 2009 Boris Schaeling
|
ian@0
|
8 // Copyright (c) 2010 Felipe Tanus, Boris Schaeling
|
ian@0
|
9 //
|
ian@0
|
10 // Distributed under the Boost Software License, Version 1.0. (See accompanying
|
ian@0
|
11 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
ian@0
|
12 //
|
ian@0
|
13
|
ian@0
|
14 /**
|
ian@0
|
15 * \file boost/process/detail/status_impl.hpp
|
ian@0
|
16 *
|
ian@0
|
17 * Includes the declaration of the status implementation class.
|
ian@0
|
18 */
|
ian@0
|
19
|
ian@0
|
20 #ifndef BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
|
ian@0
|
21 #define BOOST_PROCESS_DETAIL_STATUS_IMPL_HPP
|
ian@0
|
22
|
ian@0
|
23 #include <boost/process/config.hpp>
|
ian@0
|
24
|
ian@0
|
25 #if defined(BOOST_POSIX_API)
|
ian@0
|
26 # include <sys/types.h>
|
ian@0
|
27 # include <signal.h>
|
ian@0
|
28 # include <sys/wait.h>
|
ian@0
|
29 # include <errno.h>
|
ian@0
|
30 #elif defined(BOOST_WINDOWS_API)
|
ian@0
|
31 # include <windows.h>
|
ian@0
|
32 #else
|
ian@0
|
33 # error "Unsupported platform."
|
ian@0
|
34 #endif
|
ian@0
|
35
|
ian@0
|
36 #include <boost/process/pid_type.hpp>
|
ian@0
|
37 #include <boost/system/error_code.hpp>
|
ian@0
|
38 #include <boost/ptr_container/ptr_unordered_map.hpp>
|
ian@0
|
39 #include <algorithm>
|
ian@0
|
40
|
ian@0
|
41 namespace boost {
|
ian@0
|
42 namespace process {
|
ian@0
|
43 namespace detail {
|
ian@0
|
44
|
ian@0
|
45 #if defined(BOOST_POSIX_API)
|
ian@0
|
46 typedef pid_t phandle;
|
ian@0
|
47 #elif defined(BOOST_WINDOWS_API)
|
ian@0
|
48 typedef HANDLE phandle;
|
ian@0
|
49 #endif
|
ian@0
|
50
|
ian@0
|
51 struct operation
|
ian@0
|
52 {
|
ian@0
|
53 virtual void operator()(int exit_code)
|
ian@0
|
54 {
|
ian@0
|
55 #if defined(BOOST_MSVC)
|
ian@0
|
56 exit_code;
|
ian@0
|
57 #endif
|
ian@0
|
58 }
|
ian@0
|
59 };
|
ian@0
|
60
|
ian@0
|
61 template <typename Handler>
|
ian@0
|
62 class wrapped_handler : public operation
|
ian@0
|
63 {
|
ian@0
|
64 public:
|
ian@0
|
65 wrapped_handler(Handler handler)
|
ian@0
|
66 : handler_(handler)
|
ian@0
|
67 {
|
ian@0
|
68 }
|
ian@0
|
69
|
ian@0
|
70 void operator()(int exit_code)
|
ian@0
|
71 {
|
ian@0
|
72 handler_(boost::system::error_code(), exit_code);
|
ian@0
|
73 }
|
ian@0
|
74
|
ian@0
|
75 private:
|
ian@0
|
76 Handler handler_;
|
ian@0
|
77 };
|
ian@0
|
78
|
ian@0
|
79 /**
|
ian@0
|
80 * The status_impl class saves internal data of every status I/O object.
|
ian@0
|
81 */
|
ian@0
|
82 class status_impl
|
ian@0
|
83 {
|
ian@0
|
84 public:
|
ian@0
|
85 #if defined(BOOST_WINDOWS_API)
|
ian@0
|
86 template <typename Container>
|
ian@0
|
87 void clear(Container &handles)
|
ian@0
|
88 {
|
ian@0
|
89 for (operations_type::iterator it = ops_.begin(); it != ops_.end();
|
ian@0
|
90 ++it)
|
ian@0
|
91 {
|
ian@0
|
92 for (typename Container::iterator it2 = handles.begin(); it2 !=
|
ian@0
|
93 handles.end(); ++it2)
|
ian@0
|
94 {
|
ian@0
|
95 if (*it2 == it->first)
|
ian@0
|
96 {
|
ian@0
|
97 handles.erase(it2);
|
ian@0
|
98 break;
|
ian@0
|
99 }
|
ian@0
|
100 }
|
ian@0
|
101 CloseHandle(it->first);
|
ian@0
|
102 }
|
ian@0
|
103 }
|
ian@0
|
104 #endif
|
ian@0
|
105
|
ian@0
|
106 int wait(pid_type pid, boost::system::error_code &ec)
|
ian@0
|
107 {
|
ian@0
|
108 #if defined(BOOST_POSIX_API)
|
ian@0
|
109 pid_t p;
|
ian@0
|
110 int status;
|
ian@0
|
111 do
|
ian@0
|
112 {
|
ian@0
|
113 p = waitpid(pid, &status, 0);
|
ian@0
|
114 } while (p == -1 && errno == EINTR);
|
ian@0
|
115 if (p == -1)
|
ian@0
|
116 {
|
ian@0
|
117 ec = boost::system::error_code(errno,
|
ian@0
|
118 boost::system::get_system_category());
|
ian@0
|
119 return -1;
|
ian@0
|
120 }
|
ian@0
|
121 return status;
|
ian@0
|
122 #elif defined(BOOST_WINDOWS_API)
|
ian@0
|
123 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | SYNCHRONIZE, FALSE,
|
ian@0
|
124 pid);
|
ian@0
|
125 if (h == NULL)
|
ian@0
|
126 {
|
ian@0
|
127 ec = boost::system::error_code(GetLastError(),
|
ian@0
|
128 boost::system::get_system_category());
|
ian@0
|
129 return -1;
|
ian@0
|
130 }
|
ian@0
|
131
|
ian@0
|
132 if (WaitForSingleObject(h, INFINITE) == WAIT_FAILED)
|
ian@0
|
133 {
|
ian@0
|
134 CloseHandle(h);
|
ian@0
|
135 ec = boost::system::error_code(GetLastError(),
|
ian@0
|
136 boost::system::get_system_category());
|
ian@0
|
137 return -1;
|
ian@0
|
138 }
|
ian@0
|
139
|
ian@0
|
140 DWORD exit_code;
|
ian@0
|
141 if (!GetExitCodeProcess(h, &exit_code))
|
ian@0
|
142 {
|
ian@0
|
143 CloseHandle(h);
|
ian@0
|
144 ec = boost::system::error_code(GetLastError(),
|
ian@0
|
145 boost::system::get_system_category());
|
ian@0
|
146 return -1;
|
ian@0
|
147 }
|
ian@0
|
148 if (!CloseHandle(h))
|
ian@0
|
149 {
|
ian@0
|
150 ec = boost::system::error_code(GetLastError(),
|
ian@0
|
151 boost::system::get_system_category());
|
ian@0
|
152 return -1;
|
ian@0
|
153 }
|
ian@0
|
154 return exit_code;
|
ian@0
|
155 #endif
|
ian@0
|
156 }
|
ian@0
|
157
|
ian@0
|
158 template <typename Handler>
|
ian@0
|
159 void async_wait(phandle ph, Handler handler)
|
ian@0
|
160 {
|
ian@0
|
161 ops_.insert(ph, new wrapped_handler<Handler>(handler));
|
ian@0
|
162 }
|
ian@0
|
163
|
ian@0
|
164 bool complete(phandle ph, int exit_code)
|
ian@0
|
165 {
|
ian@0
|
166 boost::iterator_range<operations_type::iterator> r =
|
ian@0
|
167 ops_.equal_range(ph);
|
ian@0
|
168 if (r.empty())
|
ian@0
|
169 return false;
|
ian@0
|
170 for (operations_type::iterator it = r.begin(); it != r.end(); ++it)
|
ian@0
|
171 (*it->second)(exit_code);
|
ian@0
|
172 ops_.erase(r.begin(), r.end());
|
ian@0
|
173 #if defined(BOOST_WINDOWS_API)
|
ian@0
|
174 if (!CloseHandle(ph))
|
ian@0
|
175 BOOST_PROCESS_THROW_LAST_SYSTEM_ERROR("CloseHandle() failed");
|
ian@0
|
176 #endif
|
ian@0
|
177 return true;
|
ian@0
|
178 }
|
ian@0
|
179
|
ian@0
|
180 private:
|
ian@0
|
181 typedef boost::ptr_unordered_multimap<phandle, operation> operations_type;
|
ian@0
|
182 operations_type ops_;
|
ian@0
|
183 };
|
ian@0
|
184
|
ian@0
|
185 }
|
ian@0
|
186 }
|
ian@0
|
187 }
|
ian@0
|
188
|
ian@0
|
189 #endif
|