1 // Copyright (c) 2016 Klemens D. Morgenstern
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)
6 #ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
7 #define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
9 #include <boost/process/detail/windows/handler.hpp>
10 #include <boost/detail/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>
15 namespace boost { namespace process { namespace detail { namespace windows {
17 inline bool break_away_enabled(::boost::detail::winapi::HANDLE_ h)
19 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
21 if (!workaround::query_information_job_object(
23 workaround::JobObjectExtendedLimitInformation_,
24 static_cast<void*>(&info),
27 throw_last_error("QueryInformationJobObject() failed");
29 return (info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0;
32 inline void enable_break_away(::boost::detail::winapi::HANDLE_ h)
34 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
36 if (!workaround::query_information_job_object(
38 workaround::JobObjectExtendedLimitInformation_,
39 static_cast<void*>(&info),
42 throw_last_error("QueryInformationJobObject() failed");
44 if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
47 info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
49 if (!workaround::set_information_job_object(
51 workaround::JobObjectExtendedLimitInformation_,
52 static_cast<void*>(&info),
54 throw_last_error("SetInformationJobObject() failed");
57 inline void enable_break_away(::boost::detail::winapi::HANDLE_ h, std::error_code & ec)
59 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
62 if (!workaround::query_information_job_object(
64 workaround::JobObjectExtendedLimitInformation_,
65 static_cast<void*>(&info),
69 ec = get_last_error();
73 if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
76 info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
78 if (!workaround::set_information_job_object(
80 workaround::JobObjectExtendedLimitInformation_,
81 static_cast<void*>(&info),
84 ec = get_last_error();
94 ::boost::detail::winapi::HANDLE_ _job_object;
96 typedef ::boost::detail::winapi::HANDLE_ handle_t;
97 handle_t handle() const { return _job_object; }
99 explicit group_handle(handle_t h) :
102 enable_break_away(_job_object);
106 group_handle() : group_handle(::boost::detail::winapi::CreateJobObjectA(nullptr, nullptr))
112 ::boost::detail::winapi::CloseHandle(_job_object);
114 group_handle(const group_handle & c) = delete;
115 group_handle(group_handle && c) : _job_object(c._job_object)
117 c._job_object = ::boost::detail::winapi::invalid_handle_value;
119 group_handle &operator=(const group_handle & c) = delete;
120 group_handle &operator=(group_handle && c)
123 ::boost::detail::winapi::CloseHandle(_job_object);
124 _job_object = c._job_object;
125 c._job_object = ::boost::detail::winapi::invalid_handle_value;
129 void add(handle_t proc)
131 if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
134 void add(handle_t proc, std::error_code & ec) noexcept
136 if (!::boost::detail::winapi::AssignProcessToJobObject(_job_object, proc))
137 ec = get_last_error();
140 bool has(handle_t proc)
142 ::boost::detail::winapi::BOOL_ is;
143 if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
148 bool has(handle_t proc, std::error_code & ec) noexcept
150 ::boost::detail::winapi::BOOL_ is;
151 if (!::boost::detail::winapi::IsProcessInJob(proc, _job_object, &is))
152 ec = get_last_error();
158 return _job_object != nullptr;
163 inline void terminate(const group_handle &p)
165 if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
166 boost::process::detail::throw_last_error("TerminateJobObject() failed");
169 inline void terminate(const group_handle &p, std::error_code &ec) noexcept
171 if (!::boost::detail::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
172 ec = boost::process::detail::get_last_error();
177 inline bool in_group()
179 ::boost::detail::winapi::BOOL_ res;
180 if (!::boost::detail::winapi::IsProcessInJob(boost::detail::winapi::GetCurrentProcess(), nullptr, &res))
181 throw_last_error("IsProcessInJob failed");
191 #endif /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */