You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Job.cs 5.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. using System;
  2. using System.Diagnostics;
  3. using System.Runtime.InteropServices;
  4. using Shadowsocks.Controller;
  5. namespace Shadowsocks.Util.ProcessManagement
  6. {
  7. /*
  8. * See:
  9. * http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
  10. */
  11. public class Job : IDisposable
  12. {
  13. [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
  14. private static extern IntPtr CreateJobObject(IntPtr a, string lpName);
  15. [DllImport("kernel32.dll", SetLastError = true)]
  16. private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, UInt32 cbJobObjectInfoLength);
  17. [DllImport("kernel32.dll", SetLastError = true)]
  18. private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process);
  19. [DllImport("kernel32.dll", SetLastError = true)]
  20. [return: MarshalAs(UnmanagedType.Bool)]
  21. private static extern bool CloseHandle(IntPtr hObject);
  22. private IntPtr handle = IntPtr.Zero;
  23. private bool disposed;
  24. public Job()
  25. {
  26. handle = CreateJobObject(IntPtr.Zero, null);
  27. var extendedInfoPtr = IntPtr.Zero;
  28. var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION
  29. {
  30. LimitFlags = 0x2000
  31. };
  32. var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION
  33. {
  34. BasicLimitInformation = info
  35. };
  36. try
  37. {
  38. int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
  39. extendedInfoPtr = Marshal.AllocHGlobal(length);
  40. Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
  41. if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr,
  42. (uint) length))
  43. throw new Exception(string.Format("Unable to set information. Error: {0}",
  44. Marshal.GetLastWin32Error()));
  45. }
  46. finally
  47. {
  48. if (extendedInfoPtr != IntPtr.Zero)
  49. {
  50. Marshal.FreeHGlobal(extendedInfoPtr);
  51. extendedInfoPtr = IntPtr.Zero;
  52. }
  53. }
  54. }
  55. public void Dispose()
  56. {
  57. Dispose(true);
  58. GC.SuppressFinalize(this);
  59. }
  60. private void Dispose(bool disposing)
  61. {
  62. if (disposed) return;
  63. disposed = true;
  64. if (disposing) { }
  65. Close();
  66. }
  67. private void Close()
  68. {
  69. if (handle != IntPtr.Zero)
  70. {
  71. CloseHandle(handle);
  72. handle = IntPtr.Zero;
  73. }
  74. }
  75. ~Job()
  76. {
  77. Dispose(false);
  78. }
  79. public bool AddProcess(IntPtr processHandle)
  80. {
  81. var succ = AssignProcessToJobObject(handle, processHandle);
  82. if (!succ)
  83. {
  84. Logging.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
  85. }
  86. return succ;
  87. }
  88. public bool AddProcess(int processId)
  89. {
  90. return AddProcess(Process.GetProcessById(processId).Handle);
  91. }
  92. }
  93. #region Helper classes
  94. [StructLayout(LayoutKind.Sequential)]
  95. struct IO_COUNTERS
  96. {
  97. public UInt64 ReadOperationCount;
  98. public UInt64 WriteOperationCount;
  99. public UInt64 OtherOperationCount;
  100. public UInt64 ReadTransferCount;
  101. public UInt64 WriteTransferCount;
  102. public UInt64 OtherTransferCount;
  103. }
  104. [StructLayout(LayoutKind.Sequential)]
  105. struct JOBOBJECT_BASIC_LIMIT_INFORMATION
  106. {
  107. public Int64 PerProcessUserTimeLimit;
  108. public Int64 PerJobUserTimeLimit;
  109. public UInt32 LimitFlags;
  110. public UIntPtr MinimumWorkingSetSize;
  111. public UIntPtr MaximumWorkingSetSize;
  112. public UInt32 ActiveProcessLimit;
  113. public UIntPtr Affinity;
  114. public UInt32 PriorityClass;
  115. public UInt32 SchedulingClass;
  116. }
  117. [StructLayout(LayoutKind.Sequential)]
  118. public struct SECURITY_ATTRIBUTES
  119. {
  120. public UInt32 nLength;
  121. public IntPtr lpSecurityDescriptor;
  122. public Int32 bInheritHandle;
  123. }
  124. [StructLayout(LayoutKind.Sequential)]
  125. struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
  126. {
  127. public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
  128. public IO_COUNTERS IoInfo;
  129. public UIntPtr ProcessMemoryLimit;
  130. public UIntPtr JobMemoryLimit;
  131. public UIntPtr PeakProcessMemoryUsed;
  132. public UIntPtr PeakJobMemoryUsed;
  133. }
  134. public enum JobObjectInfoType
  135. {
  136. AssociateCompletionPortInformation = 7,
  137. BasicLimitInformation = 2,
  138. BasicUIRestrictions = 4,
  139. EndOfJobTimeInformation = 6,
  140. ExtendedLimitInformation = 9,
  141. SecurityLimitInformation = 5,
  142. GroupInformation = 11
  143. }
  144. #endregion
  145. }