]>
Commit | Line | Data |
---|---|---|
b32b8144 FG |
1 | // Copyright (c) 2006, 2007 Julio M. Merino Vidal |
2 | // Copyright (c) 2008 Ilya Sokolov, Boris Schaeling | |
3 | // Copyright (c) 2009 Boris Schaeling | |
4 | // Copyright (c) 2010 Felipe Tanus, Boris Schaeling | |
5 | // Copyright (c) 2011, 2012 Jeff Flinn, Boris Schaeling | |
6 | // Copyright (c) 2016 Klemens D. Morgenstern | |
7 | // | |
8 | // Distributed under the Boost Software License, Version 1.0. (See accompanying | |
9 | // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
10 | ||
11 | #ifndef BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP | |
12 | #define BOOST_PROCESS_WINDOWS_WAIT_FOR_EXIT_HPP | |
13 | ||
14 | #include <boost/process/detail/config.hpp> | |
15 | #include <system_error> | |
16 | #include <boost/winapi/synchronization.hpp> | |
17 | #include <boost/winapi/process.hpp> | |
18 | #include <boost/process/detail/windows/child_handle.hpp> | |
19 | #include <chrono> | |
20 | ||
21 | namespace boost { namespace process { namespace detail { namespace windows { | |
22 | ||
23 | inline void wait(child_handle &p, int & exit_code) | |
24 | { | |
25 | if (::boost::winapi::WaitForSingleObject(p.process_handle(), | |
26 | ::boost::winapi::infinite) == ::boost::winapi::wait_failed) | |
27 | throw_last_error("WaitForSingleObject() failed"); | |
28 | ||
29 | ::boost::winapi::DWORD_ _exit_code; | |
30 | if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) | |
31 | throw_last_error("GetExitCodeProcess() failed"); | |
32 | ||
33 | ::boost::winapi::CloseHandle(p.proc_info.hProcess); | |
34 | p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; | |
35 | exit_code = static_cast<int>(_exit_code); | |
36 | } | |
37 | ||
38 | inline void wait(child_handle &p, int & exit_code, std::error_code &ec) noexcept | |
39 | { | |
40 | ::boost::winapi::DWORD_ _exit_code = 1; | |
41 | ||
42 | if (::boost::winapi::WaitForSingleObject(p.process_handle(), | |
43 | ::boost::winapi::infinite) == ::boost::winapi::wait_failed) | |
44 | ec = std::error_code( | |
45 | ::boost::winapi::GetLastError(), | |
46 | std::system_category()); | |
47 | else if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) | |
48 | ec = std::error_code( | |
49 | ::boost::winapi::GetLastError(), | |
50 | std::system_category()); | |
51 | else | |
52 | ec.clear(); | |
53 | ||
54 | ::boost::winapi::CloseHandle(p.proc_info.hProcess); | |
55 | p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; | |
56 | exit_code = static_cast<int>(_exit_code); | |
57 | } | |
58 | ||
59 | ||
60 | template< class Rep, class Period > | |
61 | inline bool wait_for( | |
62 | child_handle &p, | |
63 | int & exit_code, | |
64 | const std::chrono::duration<Rep, Period>& rel_time) | |
65 | { | |
66 | ||
67 | std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time); | |
68 | ||
69 | ::boost::winapi::DWORD_ wait_code; | |
70 | wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(), | |
71 | static_cast<::boost::winapi::DWORD_>(ms.count())); | |
72 | if (wait_code == ::boost::winapi::wait_failed) | |
73 | throw_last_error("WaitForSingleObject() failed"); | |
74 | else if (wait_code == ::boost::winapi::wait_timeout) | |
75 | return false; // | |
76 | ||
77 | ::boost::winapi::DWORD_ _exit_code; | |
78 | if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) | |
79 | throw_last_error("GetExitCodeProcess() failed"); | |
80 | ||
81 | exit_code = static_cast<int>(_exit_code); | |
82 | ::boost::winapi::CloseHandle(p.proc_info.hProcess); | |
83 | p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; | |
84 | return true; | |
85 | } | |
86 | ||
87 | ||
88 | template< class Rep, class Period > | |
89 | inline bool wait_for( | |
90 | child_handle &p, | |
91 | int & exit_code, | |
92 | const std::chrono::duration<Rep, Period>& rel_time, | |
93 | std::error_code &ec) noexcept | |
94 | { | |
95 | ||
96 | std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(rel_time); | |
97 | ||
98 | ||
99 | ::boost::winapi::DWORD_ wait_code; | |
100 | wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(), | |
101 | static_cast<::boost::winapi::DWORD_>(ms.count())); | |
102 | if (wait_code == ::boost::winapi::wait_failed) | |
103 | ec = std::error_code( | |
104 | ::boost::winapi::GetLastError(), | |
105 | std::system_category()); | |
106 | else if (wait_code == ::boost::winapi::wait_timeout) | |
107 | return false; // | |
108 | ||
109 | ::boost::winapi::DWORD_ _exit_code = 1; | |
110 | if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) | |
111 | { | |
112 | ec = std::error_code( | |
113 | ::boost::winapi::GetLastError(), | |
114 | std::system_category()); | |
115 | return false; | |
116 | } | |
117 | else | |
118 | ec.clear(); | |
119 | ||
120 | exit_code = static_cast<int>(_exit_code); | |
121 | ::boost::winapi::CloseHandle(p.proc_info.hProcess); | |
122 | p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; | |
123 | return true; | |
124 | ; | |
125 | } | |
126 | ||
127 | template< class Clock, class Duration > | |
128 | inline bool wait_until( | |
129 | child_handle &p, | |
130 | int & exit_code, | |
131 | const std::chrono::time_point<Clock, Duration>& timeout_time) | |
132 | { | |
133 | std::chrono::milliseconds ms = | |
134 | std::chrono::duration_cast<std::chrono::milliseconds>( | |
135 | timeout_time - std::chrono::system_clock::now()); | |
136 | ||
137 | ::boost::winapi::DWORD_ wait_code; | |
138 | wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(), | |
139 | static_cast<::boost::winapi::DWORD_>(ms.count())); | |
140 | ||
141 | if (wait_code == ::boost::winapi::wait_failed) | |
142 | throw_last_error("WaitForSingleObject() failed"); | |
143 | else if (wait_code == ::boost::winapi::wait_timeout) | |
144 | return false; | |
145 | ||
146 | ::boost::winapi::DWORD_ _exit_code; | |
147 | if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) | |
148 | throw_last_error("GetExitCodeProcess() failed"); | |
149 | ||
150 | exit_code = static_cast<int>(_exit_code); | |
151 | ::boost::winapi::CloseHandle(p.proc_info.hProcess); | |
152 | p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; | |
153 | return true; | |
154 | } | |
155 | ||
156 | ||
157 | template< class Clock, class Duration > | |
158 | inline bool wait_until( | |
159 | child_handle &p, | |
160 | int & exit_code, | |
161 | const std::chrono::time_point<Clock, Duration>& timeout_time, | |
162 | std::error_code &ec) noexcept | |
163 | { | |
164 | std::chrono::milliseconds ms = | |
165 | std::chrono::duration_cast<std::chrono::milliseconds>( | |
166 | timeout_time - std::chrono::system_clock::now()); | |
167 | ||
168 | ::boost::winapi::DWORD_ wait_code; | |
169 | wait_code = ::boost::winapi::WaitForSingleObject(p.process_handle(), | |
170 | static_cast<::boost::winapi::DWORD_>(ms.count())); | |
171 | ||
172 | if (wait_code == ::boost::winapi::wait_failed) | |
173 | ec = std::error_code( | |
174 | ::boost::winapi::GetLastError(), | |
175 | std::system_category()); | |
176 | else if (wait_code == ::boost::winapi::wait_timeout) | |
177 | return false; | |
178 | ||
179 | ::boost::winapi::DWORD_ _exit_code; | |
180 | if (!::boost::winapi::GetExitCodeProcess(p.process_handle(), &_exit_code)) | |
181 | ec = std::error_code( | |
182 | ::boost::winapi::GetLastError(), | |
183 | std::system_category()); | |
184 | else | |
185 | ec.clear(); | |
186 | ||
187 | exit_code = static_cast<int>(_exit_code); | |
188 | ::boost::winapi::CloseHandle(p.proc_info.hProcess); | |
189 | p.proc_info.hProcess = ::boost::winapi::INVALID_HANDLE_VALUE_; | |
190 | return true; | |
191 | ; | |
192 | } | |
193 | ||
194 | ||
195 | }}}} | |
196 | ||
197 | #endif |