|
|
|
|
|
|
|
|
|
import ctypes |
|
from ctypes.wintypes import BOOL, DWORD, HANDLE, LARGE_INTEGER, LPCSTR, UINT |
|
|
|
from debugpy.common import log |
|
|
|
|
|
JOBOBJECTCLASS = ctypes.c_int |
|
LPDWORD = ctypes.POINTER(DWORD) |
|
LPVOID = ctypes.c_void_p |
|
SIZE_T = ctypes.c_size_t |
|
ULONGLONG = ctypes.c_ulonglong |
|
|
|
|
|
class IO_COUNTERS(ctypes.Structure): |
|
_fields_ = [ |
|
("ReadOperationCount", ULONGLONG), |
|
("WriteOperationCount", ULONGLONG), |
|
("OtherOperationCount", ULONGLONG), |
|
("ReadTransferCount", ULONGLONG), |
|
("WriteTransferCount", ULONGLONG), |
|
("OtherTransferCount", ULONGLONG), |
|
] |
|
|
|
|
|
class JOBOBJECT_BASIC_LIMIT_INFORMATION(ctypes.Structure): |
|
_fields_ = [ |
|
("PerProcessUserTimeLimit", LARGE_INTEGER), |
|
("PerJobUserTimeLimit", LARGE_INTEGER), |
|
("LimitFlags", DWORD), |
|
("MinimumWorkingSetSize", SIZE_T), |
|
("MaximumWorkingSetSize", SIZE_T), |
|
("ActiveProcessLimit", DWORD), |
|
("Affinity", SIZE_T), |
|
("PriorityClass", DWORD), |
|
("SchedulingClass", DWORD), |
|
] |
|
|
|
|
|
class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(ctypes.Structure): |
|
_fields_ = [ |
|
("BasicLimitInformation", JOBOBJECT_BASIC_LIMIT_INFORMATION), |
|
("IoInfo", IO_COUNTERS), |
|
("ProcessMemoryLimit", SIZE_T), |
|
("JobMemoryLimit", SIZE_T), |
|
("PeakProcessMemoryUsed", SIZE_T), |
|
("PeakJobMemoryUsed", SIZE_T), |
|
] |
|
|
|
|
|
JobObjectExtendedLimitInformation = JOBOBJECTCLASS(9) |
|
|
|
JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 |
|
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000 |
|
|
|
PROCESS_TERMINATE = 0x0001 |
|
PROCESS_SET_QUOTA = 0x0100 |
|
|
|
|
|
def _errcheck(is_error_result=(lambda result: not result)): |
|
def impl(result, func, args): |
|
if is_error_result(result): |
|
log.debug("{0} returned {1}", func.__name__, result) |
|
raise ctypes.WinError() |
|
else: |
|
return result |
|
|
|
return impl |
|
|
|
|
|
kernel32 = ctypes.windll.kernel32 |
|
|
|
kernel32.AssignProcessToJobObject.errcheck = _errcheck() |
|
kernel32.AssignProcessToJobObject.restype = BOOL |
|
kernel32.AssignProcessToJobObject.argtypes = (HANDLE, HANDLE) |
|
|
|
kernel32.CreateJobObjectA.errcheck = _errcheck(lambda result: result == 0) |
|
kernel32.CreateJobObjectA.restype = HANDLE |
|
kernel32.CreateJobObjectA.argtypes = (LPVOID, LPCSTR) |
|
|
|
kernel32.OpenProcess.errcheck = _errcheck(lambda result: result == 0) |
|
kernel32.OpenProcess.restype = HANDLE |
|
kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD) |
|
|
|
kernel32.QueryInformationJobObject.errcheck = _errcheck() |
|
kernel32.QueryInformationJobObject.restype = BOOL |
|
kernel32.QueryInformationJobObject.argtypes = ( |
|
HANDLE, |
|
JOBOBJECTCLASS, |
|
LPVOID, |
|
DWORD, |
|
LPDWORD, |
|
) |
|
|
|
kernel32.SetInformationJobObject.errcheck = _errcheck() |
|
kernel32.SetInformationJobObject.restype = BOOL |
|
kernel32.SetInformationJobObject.argtypes = (HANDLE, JOBOBJECTCLASS, LPVOID, DWORD) |
|
|
|
kernel32.TerminateJobObject.errcheck = _errcheck() |
|
kernel32.TerminateJobObject.restype = BOOL |
|
kernel32.TerminateJobObject.argtypes = (HANDLE, UINT) |
|
|