Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:50:08

0001 // Copyright (c) 2016 Klemens D. Morgenstern
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
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 /* BOOST_PROCESS_DETAIL_WINDOWS_GROUP_HPP_ */