1 # Copyright (c) Microsoft Corporation. All rights reserved. 2 # Licensed under the MIT License. See LICENSE in the project root 3 # for license information. 4 5 import ctypes 6 from ctypes.wintypes import BOOL, DWORD, HANDLE, LARGE_INTEGER, LPCSTR, UINT 7 8 from debugpy.common import log 9 10 11 JOBOBJECTCLASS = ctypes.c_int 12 LPDWORD = ctypes.POINTER(DWORD) 13 LPVOID = ctypes.c_void_p 14 SIZE_T = ctypes.c_size_t 15 ULONGLONG = ctypes.c_ulonglong 16 17 18 class IO_COUNTERS(ctypes.Structure): 19 _fields_ = [ 20 ("ReadOperationCount", ULONGLONG), 21 ("WriteOperationCount", ULONGLONG), 22 ("OtherOperationCount", ULONGLONG), 23 ("ReadTransferCount", ULONGLONG), 24 ("WriteTransferCount", ULONGLONG), 25 ("OtherTransferCount", ULONGLONG), 26 ] 27 28 29 class JOBOBJECT_BASIC_LIMIT_INFORMATION(ctypes.Structure): 30 _fields_ = [ 31 ("PerProcessUserTimeLimit", LARGE_INTEGER), 32 ("PerJobUserTimeLimit", LARGE_INTEGER), 33 ("LimitFlags", DWORD), 34 ("MinimumWorkingSetSize", SIZE_T), 35 ("MaximumWorkingSetSize", SIZE_T), 36 ("ActiveProcessLimit", DWORD), 37 ("Affinity", SIZE_T), 38 ("PriorityClass", DWORD), 39 ("SchedulingClass", DWORD), 40 ] 41 42 43 class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(ctypes.Structure): 44 _fields_ = [ 45 ("BasicLimitInformation", JOBOBJECT_BASIC_LIMIT_INFORMATION), 46 ("IoInfo", IO_COUNTERS), 47 ("ProcessMemoryLimit", SIZE_T), 48 ("JobMemoryLimit", SIZE_T), 49 ("PeakProcessMemoryUsed", SIZE_T), 50 ("PeakJobMemoryUsed", SIZE_T), 51 ] 52 53 54 JobObjectExtendedLimitInformation = JOBOBJECTCLASS(9) 55 56 JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x00000800 57 JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x00002000 58 59 PROCESS_TERMINATE = 0x0001 60 PROCESS_SET_QUOTA = 0x0100 61 62 63 def _errcheck(is_error_result=(lambda result: not result)): 64 def impl(result, func, args): 65 if is_error_result(result): 66 log.debug("{0} returned {1}", func.__name__, result) 67 raise ctypes.WinError() 68 else: 69 return result 70 71 return impl 72 73 74 kernel32 = ctypes.windll.kernel32 75 76 kernel32.AssignProcessToJobObject.errcheck = _errcheck() 77 kernel32.AssignProcessToJobObject.restype = BOOL 78 kernel32.AssignProcessToJobObject.argtypes = (HANDLE, HANDLE) 79 80 kernel32.CreateJobObjectA.errcheck = _errcheck(lambda result: result == 0) 81 kernel32.CreateJobObjectA.restype = HANDLE 82 kernel32.CreateJobObjectA.argtypes = (LPVOID, LPCSTR) 83 84 kernel32.OpenProcess.errcheck = _errcheck(lambda result: result == 0) 85 kernel32.OpenProcess.restype = HANDLE 86 kernel32.OpenProcess.argtypes = (DWORD, BOOL, DWORD) 87 88 kernel32.QueryInformationJobObject.errcheck = _errcheck() 89 kernel32.QueryInformationJobObject.restype = BOOL 90 kernel32.QueryInformationJobObject.argtypes = ( 91 HANDLE, 92 JOBOBJECTCLASS, 93 LPVOID, 94 DWORD, 95 LPDWORD, 96 ) 97 98 kernel32.SetInformationJobObject.errcheck = _errcheck() 99 kernel32.SetInformationJobObject.restype = BOOL 100 kernel32.SetInformationJobObject.argtypes = (HANDLE, JOBOBJECTCLASS, LPVOID, DWORD) 101 102 kernel32.TerminateJobObject.errcheck = _errcheck() 103 kernel32.TerminateJobObject.restype = BOOL 104 kernel32.TerminateJobObject.argtypes = (HANDLE, UINT) 105