13 #ifndef __STOUT_WINDOWS_JOBOBJECT_HPP__ 14 #define __STOUT_WINDOWS_JOBOBJECT_HPP__ 45 return wide_stringify(alpha_pid.
get());
55 const DWORD desired_access,
56 const BOOL inherit_handles,
57 const std::wstring&
name)
60 ::OpenJobObjectW(desired_access, inherit_handles, name.data()),
65 "os::open_job: Call to `OpenJobObject` failed for job: " +
74 const DWORD desired_access,
const BOOL inherit_handles,
const pid_t pid)
81 return open_job(desired_access, inherit_handles, name.
get());
96 "os::create_job: Call to `CreateJobObject` failed for job: " +
116 JOBOBJECT_BASIC_ACCOUNTING_INFORMATION info = {};
118 const BOOL result = ::QueryInformationJobObject(
120 JobObjectBasicAccountingInformation,
124 if (result == FALSE) {
126 "os::get_job_info: call to `QueryInformationJobObject` failed");
133 template <
size_t max_p
ids>
142 DWORD NumberOfAssignedProcesses;
143 DWORD NumberOfProcessIdsInList;
144 DWORD ProcessIdList[max_pids];
147 const BOOL result = ::QueryInformationJobObject(
149 JobObjectBasicProcessIdList,
150 reinterpret_cast<JOBOBJECT_BASIC_PROCESS_ID_LIST*
>(&pid_list),
155 if (result == FALSE && ::GetLastError() == ERROR_MORE_DATA) {
159 if (result == FALSE) {
161 "os::_get_job_processes: call to `QueryInformationJobObject` failed");
165 for (DWORD i = 0; i < pid_list.NumberOfProcessIdsInList; ++i) {
168 processes.insert(process.
get());
187 os::_get_job_processes<32>(job_handle.
get());
188 if (result.isError()) {
189 return Error(result.error());
190 }
else if (result.isSome()) {
194 result = os::_get_job_processes<32 * 32>(job_handle.
get());
195 if (result.isError()) {
196 return Error(result.error());
197 }
else if (result.isSome()) {
201 result = os::_get_job_processes<32 * 32 * 32>(job_handle.
get());
202 if (result.isError()) {
203 return Error(result.error());
204 }
else if (result.isSome()) {
210 return Error(
"os::get_job_processes: failed to get processes");
221 return std::accumulate(
230 return bytes +
process.rss.get();
248 JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = {};
249 info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
251 const BOOL result = ::SetInformationJobObject(
253 JobObjectExtendedLimitInformation,
257 if (result == FALSE) {
259 "os::set_job_kill_on_close_limit: call to `SetInformationJobObject` " 274 JOBOBJECT_CPU_RATE_CONTROL_INFORMATION control_info = {};
275 control_info.ControlFlags =
276 JOB_OBJECT_CPU_RATE_CONTROL_ENABLE | JOB_OBJECT_CPU_RATE_CONTROL_HARD_CAP;
292 const long total_cpus =
os::cpus().get();
294 const long cycles =
static_cast<long>((cpus / total_cpus) * 10000L);
296 control_info.CpuRate =
static_cast<DWORD
>(cpu_rate);
303 const BOOL result = ::SetInformationJobObject(
305 JobObjectCpuRateControlInformation,
307 sizeof(control_info));
308 if (result == FALSE) {
310 "os::set_job_cpu_limit: call to `SetInformationJobObject` failed");
324 JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = {};
325 info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_MEMORY;
326 info.JobMemoryLimit = limit.
bytes();
334 const BOOL result = ::SetInformationJobObject(
336 JobObjectExtendedLimitInformation,
339 if (result == FALSE) {
341 "os::set_job_mem_limit: call to `SetInformationJobObject` failed");
357 PROCESS_SET_QUOTA | PROCESS_TERMINATE,
363 return WindowsError(
"os::assign_job: Call to `OpenProcess` failed");
366 const BOOL result = ::AssignProcessToJobObject(
369 if (result == FALSE) {
371 "os::assign_job: Call to `AssignProcessToJobObject` failed");
383 const BOOL result = ::TerminateJobObject(
388 if (result == FALSE) {
389 return WindowsError(
"os::kill_job: Call to `TerminateJobObject` failed");
397 #endif // __STOUT_WINDOWS_JOBOBJECT_HPP__ Definition: nothing.hpp:16
Definition: errorbase.hpp:36
T & get()&
Definition: try.hpp:80
HANDLE get_handle() const
Definition: windows.hpp:90
Definition: windows.hpp:72
Try< std::list< Process > > processes()
Definition: os.hpp:184
Definition: error.hpp:108
Definition: posix_signalhandler.hpp:23
Try< std::wstring > name_job(pid_t pid)
Definition: jobobject.hpp:39
Try< Nothing > set_job_mem_limit(pid_t pid, Bytes limit)
Definition: jobobject.hpp:322
Try< Nothing > assign_job(SharedHandle job_handle, pid_t pid)
Definition: jobobject.hpp:351
Try< SharedHandle > open_job(const DWORD desired_access, const BOOL inherit_handles, const std::wstring &name)
Definition: jobobject.hpp:54
DWORD pid_t
Definition: windows.hpp:181
Definition: process.hpp:32
Try< SharedHandle > create_job(const std::wstring &name)
Definition: jobobject.hpp:85
Option< T > max(const Option< T > &left, const Option< T > &right)
Definition: option.hpp:214
Try< long > cpus()
Definition: os.hpp:265
Try< Nothing > kill_job(SharedHandle job_handle)
Definition: jobobject.hpp:381
Option< T > min(const Option< T > &left, const Option< T > &right)
Definition: option.hpp:185
static Try error(const E &e)
Definition: try.hpp:43
Result< Process > process(pid_t pid)
Definition: freebsd.hpp:30
bool isError() const
Definition: try.hpp:78
Try< Bytes > get_job_mem(pid_t pid)
Definition: jobobject.hpp:214
T & get()&
Definition: result.hpp:116
Result< std::set< Process > > _get_job_processes(const SharedHandle &job_handle)
Definition: jobobject.hpp:134
Definition: executor.hpp:48
uint64_t bytes() const
Definition: bytes.hpp:79
Try< std::set< Process > > get_job_processes(pid_t pid)
Definition: jobobject.hpp:176
Try< JOBOBJECT_BASIC_ACCOUNTING_INFORMATION > get_job_info(pid_t pid)
Definition: jobobject.hpp:109
bool isSome() const
Definition: result.hpp:112
Try< Nothing > set_job_cpu_limit(pid_t pid, double cpus)
Definition: jobobject.hpp:272
Try< std::string > format(const std::string &fmt, va_list args)
Definition: format.hpp:68
std::string stringify(int flags)
Try< Nothing > set_job_kill_on_close_limit(pid_t pid)
Definition: jobobject.hpp:239
constexpr const char * name
Definition: shell.hpp:41