File indexing completed on 2025-01-18 09:50:08
0001
0002
0003
0004
0005
0006 #ifndef BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
0007 #define BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_
0008
0009 #include <boost/process/detail/windows/handler.hpp>
0010 #include <boost/winapi/jobs.hpp>
0011 #include <boost/process/detail/windows/child_handle.hpp>
0012 #include <boost/process/detail/windows/job_workaround.hpp>
0013 #include <system_error>
0014
0015 namespace boost { namespace process { namespace detail { namespace windows {
0016
0017 inline bool break_away_enabled(::boost::winapi::HANDLE_ h)
0018 {
0019 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
0020
0021 if (!workaround::query_information_job_object(
0022 h,
0023 workaround::JobObjectExtendedLimitInformation_,
0024 static_cast<void*>(&info),
0025 sizeof(info),
0026 nullptr))
0027 throw_last_error("QueryInformationJobObject() failed");
0028
0029 return (info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0;
0030 }
0031
0032 inline void enable_break_away(::boost::winapi::HANDLE_ h)
0033 {
0034 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
0035
0036 if (!workaround::query_information_job_object(
0037 h,
0038 workaround::JobObjectExtendedLimitInformation_,
0039 static_cast<void*>(&info),
0040 sizeof(info),
0041 nullptr))
0042 throw_last_error("QueryInformationJobObject() failed");
0043
0044 if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
0045 return;
0046
0047 info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
0048
0049 if (!workaround::set_information_job_object(
0050 h,
0051 workaround::JobObjectExtendedLimitInformation_,
0052 static_cast<void*>(&info),
0053 sizeof(info)))
0054 throw_last_error("SetInformationJobObject() failed");
0055 }
0056
0057 inline void enable_break_away(::boost::winapi::HANDLE_ h, std::error_code & ec)
0058 {
0059 workaround::JOBOBJECT_EXTENDED_LIMIT_INFORMATION_ info;
0060
0061
0062 if (!workaround::query_information_job_object(
0063 h,
0064 workaround::JobObjectExtendedLimitInformation_,
0065 static_cast<void*>(&info),
0066 sizeof(info),
0067 nullptr))
0068 {
0069 ec = get_last_error();
0070 return;
0071 }
0072
0073 if ((info.BasicLimitInformation.LimitFlags & workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_) != 0)
0074 return;
0075
0076 info.BasicLimitInformation.LimitFlags |= workaround::JOB_OBJECT_LIMIT_BREAKAWAY_OK_;
0077
0078 if (!workaround::set_information_job_object(
0079 h,
0080 workaround::JobObjectExtendedLimitInformation_,
0081 static_cast<void*>(&info),
0082 sizeof(info)))
0083 {
0084 ec = get_last_error();
0085 return;
0086 }
0087 }
0088
0089 inline void associate_completion_port(::boost::winapi::HANDLE_ job,
0090 ::boost::winapi::HANDLE_ io_port)
0091 {
0092 workaround::JOBOBJECT_ASSOCIATE_COMPLETION_PORT_ port;
0093 port.CompletionKey = job;
0094 port.CompletionPort = io_port;
0095
0096 if (!workaround::set_information_job_object(
0097 job,
0098 workaround::JobObjectAssociateCompletionPortInformation_,
0099 static_cast<void*>(&port),
0100 sizeof(port)))
0101 throw_last_error("SetInformationJobObject() failed");
0102 }
0103
0104 struct group_handle
0105 {
0106 ::boost::winapi::HANDLE_ _job_object;
0107 ::boost::winapi::HANDLE_ _io_port;
0108
0109 typedef ::boost::winapi::HANDLE_ handle_t;
0110 handle_t handle() const { return _job_object; }
0111
0112 explicit group_handle(handle_t h) :
0113 _job_object(h),
0114 _io_port(::CreateIoCompletionPort(::boost::winapi::INVALID_HANDLE_VALUE_, nullptr, 0, 1))
0115 {
0116 enable_break_away(_job_object);
0117 associate_completion_port(_job_object, _io_port);
0118 }
0119
0120
0121 group_handle() : group_handle(::boost::winapi::CreateJobObjectW(nullptr, nullptr))
0122 {
0123
0124 }
0125 ~group_handle()
0126 {
0127 ::boost::winapi::CloseHandle(_job_object);
0128 ::boost::winapi::CloseHandle(_io_port);
0129 }
0130 group_handle(const group_handle & c) = delete;
0131 group_handle(group_handle && c) : _job_object(c._job_object),
0132 _io_port(c._io_port)
0133 {
0134 c._job_object = ::boost::winapi::invalid_handle_value;
0135 c._io_port = ::boost::winapi::invalid_handle_value;
0136 }
0137 group_handle &operator=(const group_handle & c) = delete;
0138 group_handle &operator=(group_handle && c)
0139 {
0140 ::boost::winapi::CloseHandle(_io_port);
0141 _io_port = c._io_port;
0142 c._io_port = ::boost::winapi::invalid_handle_value;
0143
0144 ::boost::winapi::CloseHandle(_job_object);
0145 _job_object = c._job_object;
0146 c._job_object = ::boost::winapi::invalid_handle_value;
0147 return *this;
0148 }
0149
0150 void add(handle_t proc)
0151 {
0152 if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
0153 throw_last_error();
0154 }
0155 void add(handle_t proc, std::error_code & ec) noexcept
0156 {
0157 if (!::boost::winapi::AssignProcessToJobObject(_job_object, proc))
0158 ec = get_last_error();
0159 }
0160
0161 bool has(handle_t proc)
0162 {
0163 ::boost::winapi::BOOL_ is;
0164 if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
0165 throw_last_error();
0166
0167 return is!=0;
0168 }
0169 bool has(handle_t proc, std::error_code & ec) noexcept
0170 {
0171 ::boost::winapi::BOOL_ is;
0172 if (!::boost::winapi::IsProcessInJob(proc, _job_object, &is))
0173 ec = get_last_error();
0174 return is!=0;
0175 }
0176
0177 bool valid() const
0178 {
0179 return _job_object != nullptr;
0180 }
0181
0182 };
0183
0184 inline void terminate(const group_handle &p)
0185 {
0186 if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
0187 boost::process::detail::throw_last_error("TerminateJobObject() failed");
0188 }
0189
0190 inline void terminate(const group_handle &p, std::error_code &ec) noexcept
0191 {
0192 if (!::boost::winapi::TerminateJobObject(p.handle(), EXIT_FAILURE))
0193 ec = boost::process::detail::get_last_error();
0194 else
0195 ec.clear();
0196 }
0197
0198 inline bool in_group()
0199 {
0200 ::boost::winapi::BOOL_ res;
0201 if (!::boost::winapi::IsProcessInJob(boost::winapi::GetCurrentProcess(), nullptr, &res))
0202 throw_last_error("IsProcessInJob failed");
0203
0204 return res!=0;
0205 }
0206
0207
0208
0209 }}}}
0210
0211
0212 #endif