]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/process/detail/windows/group_handle.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / process / detail / windows / group_handle.hpp
1 // Copyright (c) 2016 Klemens D. Morgenstern
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 #ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
7 #define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
8
9 #include <boost/process/detail/windows/handler.hpp>
10 #include <boost/winapi/jobs.hpp>
11 #include <boost/process/detail/windows/child_handle.hpp>
12 #include <boost/process/detail/windows/job_workaround.hpp>
13 #include <system_error>
14
15 namespace boost { namespace process { namespace detail { namespace windows {
16
17 inline bool break_away_enabled(::boost::winapi::HANDLE_ h)
18 {
19 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
20
21 if (!workaround::query_information_job_object(
22 h,
23 workaround::JobObjectExtendedLimitInformation_,
24 static_cast<void*>(&info),
25 sizeof(info),
26 nullptr))
27 throw_last_error("QueryInformationJobObject() failed");
28
29 return (info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0;
30 }
31
32 inline void enable_break_away(::boost::winapi::HANDLE_ h)
33 {
34 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
35
36 if (!workaround::query_information_job_object(
37 h,
38 workaround::JobObjectExtendedLimitInformation_,
39 static_cast<void*>(&info),
40 sizeof(info),
41 nullptr))
42 throw_last_error("QueryInformationJobObject() failed");
43
44 if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
45 return;
46
47 info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
48
49 if (!workaround::set_information_job_object(
50 h,
51 workaround::JobObjectExtendedLimitInformation_,
52 static_cast<void*>(&info),
53 sizeof(info)))
54 throw_last_error("SetInformationJobObject() failed");
55 }
56
57 inline void enable_break_away(::boost::winapi::HANDLE_ h, std::error_code & ec)
58 {
59 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
60
61
62 if (!workaround::query_information_job_object(
63 h,
64 workaround::JobObjectExtendedLimitInformation_,
65 static_cast<void*>(&info),
66 sizeof(info),
67 nullptr))
68 {
69 ec = get_last_error();
70 return;
71 }
72
73 if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
74 return;
75
76 info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
77
78 if (!workaround::set_information_job_object(
79 h,
80 workaround::JobObjectExtendedLimitInformation_,
81 static_cast<void*>(&info),
82 sizeof(info)))
83 {
84 ec = get_last_error();
85 return;
86 }
87 }
88
89 inline void associate_completion_port(::boost::winapi::HANDLE_ job,
90 ::boost::winapi::HANDLE_ io_port)
91 {
92 workaround::JOBOBJECT_ASSOCIATE_COMPLETION_PORT_ port;
93 port.CompletionKey = job;
94 port.CompletionPort = io_port;
95
96 if (!workaround::set_information_job_object(
97 job,
98 workaround::JobObjectAssociateCompletionPortInformation_,
99 static_cast<void*>(&port),
100 sizeof(port)))
101 throw_last_error("SetInformationJobObject() failed");
102 }
103
104 struct group_handle
105 {
106 ::boost::winapi::HANDLE_ _job_object;
107 ::boost::winapi::HANDLE_ _io_port;
108
109 typedef ::boost::winapi::HANDLE_ handle_t;
110 handle_t handle() const { return _job_object; }
111
112 explicit group_handle(handle_t h) :
113 _job_object(h),
114 _io_port(::CreateIoCompletionPort(::boost::winapi::INVALID_HANDLE_VALUE_, nullptr, 0, 1))
115 {
116 enable_break_away(_job_object);
117 associate_completion_port(_job_object, _io_port);
118 }
119
120
121 group_handle() : group_handle(::boost::winapi::CreateJobObjectW(nullptr, nullptr))
122 {
123
124 }
125 ~group_handle()
126 {
127 ::boost::winapi::CloseHandle(_job_object);
128 ::boost::winapi::CloseHandle(_io_port);
129 }
130 group_handle(const group_handle & c) = delete;
131 group_handle(group_handle && c) : _job_object(c._job_object),
132 _io_port(c._io_port)
133 {
134 c._job_object = ::boost::winapi::invalid_handle_value;
135 c._io_port = ::boost::winapi::invalid_handle_value;
136 }
137 group_handle &operator=(const group_handle & c) = delete;
138 group_handle &operator=(group_handle && c)
139 {
140 ::boost::winapi::CloseHandle(_io_port);
141 _io_port = c._io_port;
142 c._io_port = ::boost::winapi::invalid_handle_value;
143
144 ::boost::winapi::CloseHandle(_job_object);
145 _job_object = c._job_object;
146 c._job_object = ::boost::winapi::invalid_handle_value;
147 return *this;
148 }
149
150 void add(handle_t proc)
151 {
152 if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
153 throw_last_error();
154 }
155 void add(handle_t proc, std::error_code & ec) noexcept
156 {
157 if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
158 ec = get_last_error();
159 }
160
161 bool has(handle_t proc)
162 {
163 ::boost::winapi::BOOL_ is;
164 if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
165 throw_last_error();
166
167 return is!=0;
168 }
169 bool has(handle_t proc, std::error_code & ec) noexcept
170 {
171 ::boost::winapi::BOOL_ is;
172 if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
173 ec = get_last_error();
174 return is!=0;
175 }
176
177 bool valid() const
178 {
179 return _job_object != nullptr;
180 }
181
182 };
183
184 inline void terminate(const group_handle &p)
185 {
186 if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
187 boost::process::detail::throw_last_error("TerminateJobObject() failed");
188 }
189
190 inline void terminate(const group_handle &p, std::error_code &ec) noexcept
191 {
192 if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
193 ec = boost::process::detail::get_last_error();
194 else
195 ec.clear();
196 }
197
198 inline bool in_group()
199 {
200 ::boost::winapi::BOOL_ res;
201 if (!::boost::winapi::IsProcessInJob(boost::winapi::GetCurrentProcess(), nullptr, &res))
202 throw_last_error("IsProcessInJob failed");
203
204 return res!=0;
205 }
206
207
208
209 }}}}
210
211
212 #endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */