Format: text/x-python
⬇ Download File (3.2 KB)
   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