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.5 kB

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