OLD | NEW |
(Empty) | |
| 1 # This Source Code Form is subject to the terms of the Mozilla Public |
| 2 # License, v. 2.0. If a copy of the MPL was not distributed with this file, |
| 3 # You can obtain one at http://mozilla.org/MPL/2.0/. |
| 4 |
| 5 from ctypes import c_void_p, POINTER, sizeof, Structure, windll, WinError, WINFU
NCTYPE, addressof, c_size_t, c_ulong |
| 6 from ctypes.wintypes import BOOL, BYTE, DWORD, HANDLE, LARGE_INTEGER |
| 7 |
| 8 LPVOID = c_void_p |
| 9 LPDWORD = POINTER(DWORD) |
| 10 SIZE_T = c_size_t |
| 11 ULONG_PTR = POINTER(c_ulong) |
| 12 |
| 13 # A ULONGLONG is a 64-bit unsigned integer. |
| 14 # Thus there are 8 bytes in a ULONGLONG. |
| 15 # XXX why not import c_ulonglong ? |
| 16 ULONGLONG = BYTE * 8 |
| 17 |
| 18 class IO_COUNTERS(Structure): |
| 19 # The IO_COUNTERS struct is 6 ULONGLONGs. |
| 20 # TODO: Replace with non-dummy fields. |
| 21 _fields_ = [('dummy', ULONGLONG * 6)] |
| 22 |
| 23 class JOBOBJECT_BASIC_ACCOUNTING_INFORMATION(Structure): |
| 24 _fields_ = [('TotalUserTime', LARGE_INTEGER), |
| 25 ('TotalKernelTime', LARGE_INTEGER), |
| 26 ('ThisPeriodTotalUserTime', LARGE_INTEGER), |
| 27 ('ThisPeriodTotalKernelTime', LARGE_INTEGER), |
| 28 ('TotalPageFaultCount', DWORD), |
| 29 ('TotalProcesses', DWORD), |
| 30 ('ActiveProcesses', DWORD), |
| 31 ('TotalTerminatedProcesses', DWORD)] |
| 32 |
| 33 class JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION(Structure): |
| 34 _fields_ = [('BasicInfo', JOBOBJECT_BASIC_ACCOUNTING_INFORMATION), |
| 35 ('IoInfo', IO_COUNTERS)] |
| 36 |
| 37 # see http://msdn.microsoft.com/en-us/library/ms684147%28VS.85%29.aspx |
| 38 class JOBOBJECT_BASIC_LIMIT_INFORMATION(Structure): |
| 39 _fields_ = [('PerProcessUserTimeLimit', LARGE_INTEGER), |
| 40 ('PerJobUserTimeLimit', LARGE_INTEGER), |
| 41 ('LimitFlags', DWORD), |
| 42 ('MinimumWorkingSetSize', SIZE_T), |
| 43 ('MaximumWorkingSetSize', SIZE_T), |
| 44 ('ActiveProcessLimit', DWORD), |
| 45 ('Affinity', ULONG_PTR), |
| 46 ('PriorityClass', DWORD), |
| 47 ('SchedulingClass', DWORD) |
| 48 ] |
| 49 |
| 50 class JOBOBJECT_ASSOCIATE_COMPLETION_PORT(Structure): |
| 51 _fields_ = [('CompletionKey', c_ulong), |
| 52 ('CompletionPort', HANDLE)] |
| 53 |
| 54 # see http://msdn.microsoft.com/en-us/library/ms684156%28VS.85%29.aspx |
| 55 class JOBOBJECT_EXTENDED_LIMIT_INFORMATION(Structure): |
| 56 _fields_ = [('BasicLimitInformation', JOBOBJECT_BASIC_LIMIT_INFORMATION), |
| 57 ('IoInfo', IO_COUNTERS), |
| 58 ('ProcessMemoryLimit', SIZE_T), |
| 59 ('JobMemoryLimit', SIZE_T), |
| 60 ('PeakProcessMemoryUsed', SIZE_T), |
| 61 ('PeakJobMemoryUsed', SIZE_T)] |
| 62 |
| 63 # These numbers below come from: |
| 64 # http://msdn.microsoft.com/en-us/library/ms686216%28v=vs.85%29.aspx |
| 65 JobObjectAssociateCompletionPortInformation = 7 |
| 66 JobObjectBasicAndIoAccountingInformation = 8 |
| 67 JobObjectExtendedLimitInformation = 9 |
| 68 |
| 69 class JobObjectInfo(object): |
| 70 mapping = { 'JobObjectBasicAndIoAccountingInformation': 8, |
| 71 'JobObjectExtendedLimitInformation': 9, |
| 72 'JobObjectAssociateCompletionPortInformation': 7 |
| 73 } |
| 74 structures = { |
| 75 7: JOBOBJECT_ASSOCIATE_COMPLETION_PORT, |
| 76 8: JOBOBJECT_BASIC_AND_IO_ACCOUNTING_INFORMATION, |
| 77 9: JOBOBJECT_EXTENDED_LIMIT_INFORMATION |
| 78 } |
| 79 def __init__(self, _class): |
| 80 if isinstance(_class, basestring): |
| 81 assert _class in self.mapping, 'Class should be one of %s; you gave
%s' % (self.mapping, _class) |
| 82 _class = self.mapping[_class] |
| 83 assert _class in self.structures, 'Class should be one of %s; you gave %
s' % (self.structures, _class) |
| 84 self.code = _class |
| 85 self.info = self.structures[_class]() |
| 86 |
| 87 |
| 88 QueryInformationJobObjectProto = WINFUNCTYPE( |
| 89 BOOL, # Return type |
| 90 HANDLE, # hJob |
| 91 DWORD, # JobObjectInfoClass |
| 92 LPVOID, # lpJobObjectInfo |
| 93 DWORD, # cbJobObjectInfoLength |
| 94 LPDWORD # lpReturnLength |
| 95 ) |
| 96 |
| 97 QueryInformationJobObjectFlags = ( |
| 98 (1, 'hJob'), |
| 99 (1, 'JobObjectInfoClass'), |
| 100 (1, 'lpJobObjectInfo'), |
| 101 (1, 'cbJobObjectInfoLength'), |
| 102 (1, 'lpReturnLength', None) |
| 103 ) |
| 104 |
| 105 _QueryInformationJobObject = QueryInformationJobObjectProto( |
| 106 ('QueryInformationJobObject', windll.kernel32), |
| 107 QueryInformationJobObjectFlags |
| 108 ) |
| 109 |
| 110 class SubscriptableReadOnlyStruct(object): |
| 111 def __init__(self, struct): |
| 112 self._struct = struct |
| 113 |
| 114 def _delegate(self, name): |
| 115 result = getattr(self._struct, name) |
| 116 if isinstance(result, Structure): |
| 117 return SubscriptableReadOnlyStruct(result) |
| 118 return result |
| 119 |
| 120 def __getitem__(self, name): |
| 121 match = [fname for fname, ftype in self._struct._fields_ |
| 122 if fname == name] |
| 123 if match: |
| 124 return self._delegate(name) |
| 125 raise KeyError(name) |
| 126 |
| 127 def __getattr__(self, name): |
| 128 return self._delegate(name) |
| 129 |
| 130 def QueryInformationJobObject(hJob, JobObjectInfoClass): |
| 131 jobinfo = JobObjectInfo(JobObjectInfoClass) |
| 132 result = _QueryInformationJobObject( |
| 133 hJob=hJob, |
| 134 JobObjectInfoClass=jobinfo.code, |
| 135 lpJobObjectInfo=addressof(jobinfo.info), |
| 136 cbJobObjectInfoLength=sizeof(jobinfo.info) |
| 137 ) |
| 138 if not result: |
| 139 raise WinError() |
| 140 return SubscriptableReadOnlyStruct(jobinfo.info) |
OLD | NEW |