-
Notifications
You must be signed in to change notification settings - Fork 325
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Procdump Arguments Changed #1700
Changes from all commits
3f228ab
3ced475
a236fd3
65a3263
5da69bf
6c70874
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces | ||
{ | ||
using System; | ||
|
||
public interface INativeMethodsHelper | ||
{ | ||
/// <summary> | ||
/// Returns if a process is 64 bit process | ||
/// </summary> | ||
/// <param name="processHandle">Process Handle</param> | ||
/// <returns>Bool for Is64Bit</returns> | ||
bool Is64Bit(IntPtr processHandle); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE file in the project root for full license information. | ||
|
||
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector | ||
{ | ||
using System; | ||
using System.Runtime.InteropServices; | ||
using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces; | ||
using Microsoft.VisualStudio.TestPlatform.ObjectModel; | ||
|
||
public class NativeMethodsHelper : INativeMethodsHelper | ||
{ | ||
/// <summary> | ||
/// Returns if a process is 64 bit process | ||
/// </summary> | ||
/// <param name="processHandle">Process Handle</param> | ||
/// <returns>Bool for Is64Bit</returns> | ||
public bool Is64Bit(IntPtr processHandle) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this work for 32 bit os as well There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We use this condition only for 64 bit |
||
// WOW64 is the x86 emulator that allows 32 bit Windows - based applications to run seamlessly on 64 bit Windows. | ||
bool isWow64 = false; | ||
|
||
// If the function succeeds, the return value is a nonzero value. | ||
if (!IsWow64Process(processHandle, out isWow64)) | ||
{ | ||
if (EqtTrace.IsVerboseEnabled) | ||
{ | ||
EqtTrace.Verbose("NativeMethodsHelper: The call to IsWow64Process failed."); | ||
} | ||
} | ||
|
||
return !isWow64; | ||
} | ||
|
||
// A pointer to a value that is set to TRUE if the process is running under WOW64. | ||
// If the process is running under 32-bit Windows, the value is set to FALSE. | ||
// If the process is a 64-bit application running under 64-bit Windows, the value is also set to FALSE. | ||
[DllImport("kernel32.dll", SetLastError = true, CallingConvention = CallingConvention.Winapi)] | ||
[return: MarshalAs(UnmanagedType.Bool)] | ||
internal static extern bool IsWow64Process([In] IntPtr process, [Out] out bool wow64Process); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,9 +4,11 @@ | |
namespace Microsoft.TestPlatform.Extensions.BlameDataCollector | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Globalization; | ||
using System.IO; | ||
using System.Text; | ||
using Microsoft.TestPlatform.Extensions.BlameDataCollector.Interfaces; | ||
using Microsoft.VisualStudio.TestPlatform.ObjectModel; | ||
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions; | ||
using Microsoft.VisualStudio.TestPlatform.PlatformAbstractions.Interfaces; | ||
|
@@ -15,27 +17,35 @@ namespace Microsoft.TestPlatform.Extensions.BlameDataCollector | |
|
||
public class ProcessDumpUtility : IProcessDumpUtility | ||
{ | ||
private static List<string> procDumpExceptionsList; | ||
private IProcessHelper processHelper; | ||
private IFileHelper fileHelper; | ||
private IEnvironment environment; | ||
private Process procDumpProcess; | ||
private string testResultsDirectory; | ||
private string dumpFileName; | ||
private INativeMethodsHelper nativeMethodsHelper; | ||
|
||
public ProcessDumpUtility() | ||
: this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment()) | ||
: this(new ProcessHelper(), new FileHelper(), new PlatformEnvironment(), new NativeMethodsHelper()) | ||
{ | ||
} | ||
|
||
public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment) | ||
public ProcessDumpUtility(IProcessHelper processHelper, IFileHelper fileHelper, IEnvironment environment, INativeMethodsHelper nativeMethodsHelper) | ||
{ | ||
this.processHelper = processHelper; | ||
this.fileHelper = fileHelper; | ||
this.environment = environment; | ||
this.nativeMethodsHelper = nativeMethodsHelper; | ||
ProcessDumpUtility.procDumpExceptionsList = new List<string>() | ||
{ | ||
"STACK_OVERFLOW", | ||
"ACCESS_VIOLATION" | ||
}; | ||
} | ||
|
||
/// <inheritdoc/> | ||
public string GetDumpFile() | ||
/// <inheritdoc/> | ||
public string GetDumpFile() | ||
{ | ||
if (this.procDumpProcess == null) | ||
{ | ||
|
@@ -77,7 +87,7 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu | |
this.testResultsDirectory = testResultsDirectory; | ||
|
||
this.procDumpProcess = this.processHelper.LaunchProcess( | ||
this.GetProcDumpExecutable(), | ||
this.GetProcDumpExecutable(processId), | ||
ProcessDumpUtility.BuildProcDumpArgs(processId, this.dumpFileName, isFullDump), | ||
testResultsDirectory, | ||
null, | ||
|
@@ -101,37 +111,57 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu | |
private static string BuildProcDumpArgs(int processId, string filename, bool isFullDump = false) | ||
{ | ||
// -accepteula: Auto accept end-user license agreement | ||
// -e: Write a dump when the process encounters an unhandled exception. Include the 1 to create dump on first chance exceptions. | ||
// -g: Run as a native debugger in a managed process (no interop). | ||
// -t: Write a dump when the process terminates. | ||
// -ma: Full dump argument. | ||
// -f: Filter the exceptions. | ||
StringBuilder procDumpArgument = new StringBuilder("-accepteula -e 1 -g -t "); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice :) |
||
if (isFullDump) | ||
{ | ||
// This will create a fulldump of the process with specified filename | ||
return "-accepteula -t -ma " + processId + " " + filename + ".dmp"; | ||
procDumpArgument.Append("-ma "); | ||
} | ||
else | ||
|
||
foreach (var exceptionFilter in ProcessDumpUtility.procDumpExceptionsList) | ||
{ | ||
// This will create a minidump of the process with specified filename | ||
return "-accepteula -t " + processId + " " + filename + ".dmp"; | ||
procDumpArgument.Append($"-f {exceptionFilter} "); | ||
} | ||
|
||
procDumpArgument.Append($"{processId} {filename}.dmp"); | ||
var argument = procDumpArgument.ToString(); | ||
|
||
if (EqtTrace.IsInfoEnabled) | ||
{ | ||
EqtTrace.Info($"ProcessDumpUtility : The procdump argument is {argument}"); | ||
} | ||
|
||
return argument; | ||
} | ||
|
||
/// <summary> | ||
/// Get procdump executable path | ||
/// </summary> | ||
/// <param name="processId"> | ||
/// Process Id | ||
/// </param> | ||
/// <returns>procdump executable path</returns> | ||
private string GetProcDumpExecutable() | ||
private string GetProcDumpExecutable(int processId) | ||
{ | ||
var procdumpPath = Environment.GetEnvironmentVariable("PROCDUMP_PATH"); | ||
|
||
if (!string.IsNullOrWhiteSpace(procdumpPath)) | ||
{ | ||
string filename = string.Empty; | ||
|
||
if (this.environment.Architecture == PlatformArchitecture.X64) | ||
// Launch procdump according to process architecture | ||
if (this.environment.Architecture == PlatformArchitecture.X86) | ||
{ | ||
filename = "procdump64.exe"; | ||
filename = Constants.ProcdumpProcess; | ||
} | ||
else if (this.environment.Architecture == PlatformArchitecture.X86) | ||
else | ||
{ | ||
filename = "procdump.exe"; | ||
filename = this.nativeMethodsHelper.Is64Bit(this.processHelper.GetProcessHandle(processId)) ? | ||
Constants.Procdump64Process : Constants.ProcdumpProcess; | ||
} | ||
|
||
var procDumpExe = Path.Combine(procdumpPath, filename); | ||
|
@@ -149,4 +179,4 @@ private string GetProcDumpExecutable() | |
} | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can remove this interface and make NativeMethodsHelper a static class as it has methods which are not using any class level variables. Also class seems more like helper class this making it static makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it via interface to use it for unit tests.