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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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;
  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)
  63. return;
  64. if (disposing) { }
  65. Close();
  66. disposed = true;
  67. }
  68. public void Close()
  69. {
  70. CloseHandle(handle);
  71. handle = IntPtr.Zero;
  72. }
  73. public bool AddProcess(IntPtr processHandle)
  74. {
  75. var succ = AssignProcessToJobObject(handle, processHandle);
  76. if (!succ)
  77. {
  78. Logging.Error("Failed to call AssignProcessToJobObject! GetLastError=" + Marshal.GetLastWin32Error());
  79. }
  80. return succ;
  81. }
  82. public bool AddProcess(int processId)
  83. {
  84. return AddProcess(Process.GetProcessById(processId).Handle);
  85. }
  86. }
  87. #region Helper classes
  88. [StructLayout(LayoutKind.Sequential)]
  89. struct IO_COUNTERS
  90. {
  91. public UInt64 ReadOperationCount;
  92. public UInt64 WriteOperationCount;
  93. public UInt64 OtherOperationCount;
  94. public UInt64 ReadTransferCount;
  95. public UInt64 WriteTransferCount;
  96. public UInt64 OtherTransferCount;
  97. }
  98. [StructLayout(LayoutKind.Sequential)]
  99. struct JOBOBJECT_BASIC_LIMIT_INFORMATION
  100. {
  101. public Int64 PerProcessUserTimeLimit;
  102. public Int64 PerJobUserTimeLimit;
  103. public UInt32 LimitFlags;
  104. public UIntPtr MinimumWorkingSetSize;
  105. public UIntPtr MaximumWorkingSetSize;
  106. public UInt32 ActiveProcessLimit;
  107. public UIntPtr Affinity;
  108. public UInt32 PriorityClass;
  109. public UInt32 SchedulingClass;
  110. }
  111. [StructLayout(LayoutKind.Sequential)]
  112. public struct SECURITY_ATTRIBUTES
  113. {
  114. public UInt32 nLength;
  115. public IntPtr lpSecurityDescriptor;
  116. public Int32 bInheritHandle;
  117. }
  118. [StructLayout(LayoutKind.Sequential)]
  119. struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION
  120. {
  121. public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation;
  122. public IO_COUNTERS IoInfo;
  123. public UIntPtr ProcessMemoryLimit;
  124. public UIntPtr JobMemoryLimit;
  125. public UIntPtr PeakProcessMemoryUsed;
  126. public UIntPtr PeakJobMemoryUsed;
  127. }
  128. public enum JobObjectInfoType
  129. {
  130. AssociateCompletionPortInformation = 7,
  131. BasicLimitInformation = 2,
  132. BasicUIRestrictions = 4,
  133. EndOfJobTimeInformation = 6,
  134. ExtendedLimitInformation = 9,
  135. SecurityLimitInformation = 5,
  136. GroupInformation = 11
  137. }
  138. #endregion
  139. }