-
Notifications
You must be signed in to change notification settings - Fork 437
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement measures to fix flakey tests (#3850)
- Loading branch information
1 parent
9e2c1a9
commit a88b2c4
Showing
8 changed files
with
491 additions
and
94 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
// Copyright (c) .NET Foundation. All rights reserved. | ||
// Licensed under the MIT License. See License.txt in the project root for license information. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.Runtime.InteropServices; | ||
|
||
namespace Azure.Functions.Cli.Common | ||
{ | ||
// Taken from: https://github.com/Azure/azure-functions-host/blob/69111926ee920d4ba10829c8fa34303bb8165a42/src/WebJobs.Script/Workers/ProcessManagement/JobObjectRegistry.cs | ||
// This kills child func.exe even if tests are killed from VS mid-run. | ||
|
||
// Registers processes on windows with a job object to ensure disposal after parent exit. | ||
internal class JobObjectRegistry : IDisposable | ||
{ | ||
private IntPtr _handle; | ||
private bool _disposed = false; | ||
|
||
public JobObjectRegistry() | ||
{ | ||
_handle = CreateJobObject(null, null); | ||
|
||
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION | ||
{ | ||
LimitFlags = 0x2000 | ||
}; | ||
|
||
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION | ||
{ | ||
BasicLimitInformation = info | ||
}; | ||
|
||
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); | ||
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); | ||
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); | ||
|
||
if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) | ||
{ | ||
throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); | ||
} | ||
} | ||
|
||
public bool Register(Process proc) | ||
{ | ||
return AssignProcessToJobObject(_handle, proc.Handle); | ||
} | ||
|
||
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)] | ||
private static extern IntPtr CreateJobObject(object a, string lpName); | ||
|
||
[DllImport("kernel32.dll", SetLastError = true)] | ||
private static extern bool SetInformationJobObject(IntPtr hJob, JobObjectInfoType infoType, IntPtr lpJobObjectInfo, uint cbJobObjectInfoLength); | ||
|
||
[DllImport("kernel32.dll", SetLastError = true)] | ||
private static extern bool AssignProcessToJobObject(IntPtr job, IntPtr process); | ||
|
||
[DllImport("kernel32.dll", SetLastError = true)] | ||
private static extern bool CloseHandle(IntPtr job); | ||
|
||
public void Dispose() | ||
{ | ||
Dispose(true); | ||
GC.SuppressFinalize(this); | ||
} | ||
|
||
private void Dispose(bool disposing) | ||
{ | ||
if (_disposed) | ||
{ | ||
return; | ||
} | ||
|
||
if (disposing) | ||
{ | ||
// Dispose of managed resources. | ||
} | ||
|
||
Close(); | ||
_disposed = true; | ||
} | ||
|
||
public void Close() | ||
{ | ||
if (_handle != IntPtr.Zero) | ||
{ | ||
CloseHandle(_handle); | ||
} | ||
_handle = IntPtr.Zero; | ||
} | ||
} | ||
|
||
public enum JobObjectInfoType | ||
{ | ||
AssociateCompletionPortInformation = 7, | ||
BasicLimitInformation = 2, | ||
BasicUIRestrictions = 4, | ||
EndOfJobTimeInformation = 6, | ||
ExtendedLimitInformation = 9, | ||
SecurityLimitInformation = 5, | ||
GroupInformation = 11 | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct IO_COUNTERS | ||
{ | ||
public ulong ReadOperationCount; | ||
public ulong WriteOperationCount; | ||
public ulong OtherOperationCount; | ||
public ulong ReadTransferCount; | ||
public ulong WriteTransferCount; | ||
public ulong OtherTransferCount; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct JOBOBJECT_BASIC_LIMIT_INFORMATION | ||
{ | ||
public long PerProcessUserTimeLimit; | ||
public long PerJobUserTimeLimit; | ||
public uint LimitFlags; | ||
public UIntPtr MinimumWorkingSetSize; | ||
public UIntPtr MaximumWorkingSetSize; | ||
public uint ActiveProcessLimit; | ||
public UIntPtr Affinity; | ||
public uint PriorityClass; | ||
public uint SchedulingClass; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
public struct SECURITY_ATTRIBUTES | ||
{ | ||
public uint nLength; | ||
public IntPtr lpSecurityDescriptor; | ||
public int bInheritHandle; | ||
} | ||
|
||
[StructLayout(LayoutKind.Sequential)] | ||
internal struct JOBOBJECT_EXTENDED_LIMIT_INFORMATION | ||
{ | ||
public JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation; | ||
public IO_COUNTERS IoInfo; | ||
public UIntPtr ProcessMemoryLimit; | ||
public UIntPtr JobMemoryLimit; | ||
public UIntPtr PeakProcessMemoryUsed; | ||
public UIntPtr PeakJobMemoryUsed; | ||
} | ||
} |
Oops, something went wrong.