Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ public class SocketCommunicationManager : ICommunicationManager
/// </summary>
private object sendSyncObject = new object();

/// <summary>
/// Sync object for receiving messages
/// </summary>
private object receiveSyncObject = new object();

private Socket socket;

/// <summary>
Expand Down Expand Up @@ -311,7 +316,11 @@ public async Task<Message> ReceiveMessageAsync(CancellationToken cancellationTok
/// <returns> Raw message string </returns>
public string ReceiveRawMessage()
{
return this.binaryReader.ReadString();
lock (this.receiveSyncObject)
{
// Reading message on binaryreader is not thread-safe
return this.binaryReader.ReadString();
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class BlameCollector : DataCollector, ITestExecutionEnvironmentSpecifier
private int testStartCount;
private int testEndCount;
private bool processDumpEnabled;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can rename this to processMiniDumpEnabled for readability

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be true irrespective of minidump or full dump is enabled. Code logic wise this is more readable. We can discuss if needed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree this makes more sense. But you are also using processFullDumpEnabled bariable to know whether full dump is enabled or not. Rather than processFullDumpEnabled it shoule take string or enum type 'full' or 'mini'. Today we are implictly deciding that if processFullDumpEnabled is false but processEnabled is true, then that means mini dump is enabled. This should be explicit.

private bool collectDumpAlways;
private bool processFullDumpEnabled;
private string attachmentGuid;

/// <summary>
Expand Down Expand Up @@ -97,12 +99,50 @@ public override void Initialize(

if (this.configurationElement != null)
{
this.processDumpEnabled = this.configurationElement[Constants.DumpModeKey] != null;
var collectDumpNode = this.configurationElement[Constants.DumpModeKey];
this.processDumpEnabled = collectDumpNode != null;
if (this.processDumpEnabled)
{
this.ValidateAndAddProcessDumpParameters(collectDumpNode);
}
}

this.attachmentGuid = Guid.NewGuid().ToString().Replace("-", string.Empty);
}

private void ValidateAndAddProcessDumpParameters(XmlElement collectDumpNode)
{
foreach (XmlAttribute attribute in collectDumpNode.Attributes)
{
if (string.Equals(attribute.Name, Constants.CollectDumpAlwaysKey, StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(attribute.Value, Constants.TrueConfigurationValue, StringComparison.OrdinalIgnoreCase) || string.Equals(attribute.Value, Constants.FalseConfigurationValue, StringComparison.OrdinalIgnoreCase))
{
bool.TryParse(attribute.Value, out this.collectDumpAlways);
}
else
{
this.logger.LogWarning(this.context.SessionDataCollectionContext, string.Format(CultureInfo.CurrentUICulture, Resources.Resources.BlameParameterValueIncorrect, attribute.Name, Constants.TrueConfigurationValue, Constants.FalseConfigurationValue));
}
}
else if (string.Equals(attribute.Name, Constants.DumpTypeKey, StringComparison.OrdinalIgnoreCase))
{
if (string.Equals(attribute.Value, Constants.FullConfigurationValue, StringComparison.OrdinalIgnoreCase) || string.Equals(attribute.Value, Constants.MiniConfigurationValue, StringComparison.OrdinalIgnoreCase))
{
this.processFullDumpEnabled = string.Equals(attribute.Value, Constants.FullConfigurationValue, StringComparison.OrdinalIgnoreCase);
}
else
{
this.logger.LogWarning(this.context.SessionDataCollectionContext, string.Format(CultureInfo.CurrentUICulture, Resources.Resources.BlameParameterValueIncorrect, attribute.Name, Constants.FullConfigurationValue, Constants.MiniConfigurationValue));
}
}
else
{
this.logger.LogWarning(this.context.SessionDataCollectionContext, string.Format(CultureInfo.CurrentUICulture, Resources.Resources.BlameParameterKeyIncorrect, attribute.Name));
}
}
}

/// <summary>
/// Called when Test Case Start event is invoked
/// </summary>
Expand Down Expand Up @@ -159,23 +199,29 @@ private void SessionEnded_Handler(object sender, SessionEndEventArgs args)

if (this.processDumpEnabled)
{
try
// If there was a test case crash or if we need to collect dump on process exit.
if (this.testStartCount > this.testEndCount || this.collectDumpAlways)
{
var dumpFile = this.processDumpUtility.GetDumpFile();
if (!string.IsNullOrEmpty(dumpFile))
try
{
var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true);
this.dataCollectionSink.SendFileAsync(fileTranferInformation);
var dumpFile = this.processDumpUtility.GetDumpFile();
if (!string.IsNullOrEmpty(dumpFile))
{
var fileTranferInformation = new FileTransferInformation(this.context.SessionDataCollectionContext, dumpFile, true);
this.dataCollectionSink.SendFileAsync(fileTranferInformation);
}
else
{
EqtTrace.Warning("BlameCollector.SessionEnded_Handler: blame:CollectDump was enabled but dump file was not generated.");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be logger warning as well as user was expecting a dump file but was not created.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

this.logger.LogWarning(args.Context, Resources.Resources.ProcDumpNotGenerated);
}
}
else
catch (FileNotFoundException ex)
{
EqtTrace.Warning("BlameCollector.SessionEnded_Handler: blame:CollectDump was enabled but dump file was not generated.");
EqtTrace.Warning(ex.Message);
this.logger.LogWarning(args.Context, ex.Message);
}
}
catch (FileNotFoundException ex)
{
this.logger.LogWarning(args.Context, ex.Message);
}
}

this.DeregisterEvents();
Expand All @@ -195,7 +241,7 @@ private void TestHostLaunched_Handler(object sender, TestHostLaunchedEventArgs a

try
{
this.processDumpUtility.StartProcessDump(args.TestHostProcessId, this.attachmentGuid, this.GetResultsDirectory());
this.processDumpUtility.StartProcessDump(args.TestHostProcessId, this.attachmentGuid, this.GetResultsDirectory(), this.processFullDumpEnabled);
}
catch (TestPlatformException e)
{
Expand All @@ -204,7 +250,7 @@ private void TestHostLaunched_Handler(object sender, TestHostLaunchedEventArgs a
EqtTrace.Warning("BlameCollector.TestHostLaunched_Handler: Could not start process dump. {0}", e);
}

this.logger.LogWarning(args.Context, e.Message);
this.logger.LogWarning(args.Context, string.Format(CultureInfo.CurrentUICulture, Resources.Resources.ProcDumpCouldNotStart, e.Message));
}
catch (Exception e)
{
Expand All @@ -213,7 +259,7 @@ private void TestHostLaunched_Handler(object sender, TestHostLaunchedEventArgs a
EqtTrace.Warning("BlameCollector.TestHostLaunched_Handler: Could not start process dump. {0}", e);
}

this.logger.LogWarning(args.Context, e.ToString());
this.logger.LogWarning(args.Context, string.Format(CultureInfo.CurrentUICulture, Resources.Resources.ProcDumpCouldNotStart, e.ToString()));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,35 @@ internal static class Constants
/// Configuration key name for dump mode
/// </summary>
public const string DumpModeKey = "CollectDump";

/// <summary>
/// Configuration key name for collect dump always
/// </summary>
public const string CollectDumpAlwaysKey = "CollectAlways";

/// <summary>
/// Configuration key name for dump type
/// </summary>
public const string DumpTypeKey = "DumpType";

/// <summary>
/// Configuration value for true
/// </summary>
public const string TrueConfigurationValue = "True";

/// <summary>
/// Configuration value for false
/// </summary>
public const string FalseConfigurationValue = "False";

/// <summary>
/// Configuration value for full
/// </summary>
public const string FullConfigurationValue = "Full";

/// <summary>
/// Configuration value for mini
/// </summary>
public const string MiniConfigurationValue = "Mini";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public interface IProcessDumpUtility
/// <param name="testResultsDirectory">
/// Path to TestResults directory
/// </param>
void StartProcessDump(int processId, string dumpFileGuid, string testResultsDirectory);
/// <param name="isFullDump">
/// Is full dump enabled
/// </param>
void StartProcessDump(int processId, string dumpFileGuid, string testResultsDirectory, bool isFullDump = false);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ public string GetDumpFile()
}

/// <inheritdoc/>
public void StartProcessDump(int processId, string dumpFileGuid, string testResultsDirectory)
public void StartProcessDump(int processId, string dumpFileGuid, string testResultsDirectory, bool isFullDump = false)
{
this.dumpFileName = $"{this.processHelper.GetProcessName(processId)}_{processId}_{dumpFileGuid}";
this.testResultsDirectory = testResultsDirectory;

this.procDumpProcess = this.processHelper.LaunchProcess(
this.GetProcDumpExecutable(),
ProcessDumpUtility.BuildProcDumpArgs(processId, this.dumpFileName),
ProcessDumpUtility.BuildProcDumpArgs(processId, this.dumpFileName, isFullDump),
testResultsDirectory,
null,
null,
Expand All @@ -94,13 +94,24 @@ public void StartProcessDump(int processId, string dumpFileGuid, string testResu
/// <param name="filename">
/// Filename for dump file
/// </param>
/// <param name="isFullDump">
/// Is full dump enabled
/// </param>
/// <returns>Arguments</returns>
private static string BuildProcDumpArgs(int processId, string filename)
private static string BuildProcDumpArgs(int processId, string filename, bool isFullDump = false)
{
// -accepteula: Auto accept end-user license agreement
// -t: Write a dump when the process terminates.
// This will create a minidump of the process with specified filename
return "-accepteula -t " + processId + " " + filename + ".dmp";
if (isFullDump)
{
// This will create a fulldump of the process with specified filename
return "-accepteula -t -ma " + processId + " " + filename + ".dmp";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this args needs to change. Please check with @abhishkk .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I'm doing this in next task. Current PR is just for the additional collector attributes

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When discussed args are added, we need to test it for all known crashes, for 32 bit and 64 bit process with 32 and 64 bit OS.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than creating separate if else, we can create a stringbuilder and not add -ma in case its mini dump. This allows us to enahance this argument creation based on any new functionality.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deferred to next refactor in line

}
else
{
// This will create a minidump of the process with specified filename
return "-accepteula -t " + processId + " " + filename + ".dmp";
}
}

/// <summary>
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,22 @@
<data name="AbortedTestRun" xml:space="preserve">
<value>The active Test Run was aborted because the host process exited unexpectedly while executing following test(s):</value>
</data>
<data name="BlameParameterKeyIncorrect" xml:space="preserve">
<value>The blame parameter key specified {0} is not valid. Ignoring this key.</value>
</data>
<data name="BlameParameterValueIncorrect" xml:space="preserve">
<value>The blame parameter key {0} can only support values {1}/{2}. Ignoring this key.</value>
</data>
<data name="DumpFileNotGeneratedErrorMessage" xml:space="preserve">
<value>Collect dump was enabled but no dump file was generated.</value>
</data>
<data name="ProcDumpCouldNotStart" xml:space="preserve">
<value>Could not start process dump: {0}</value>
</data>
<data name="ProcDumpEnvVarEmpty" xml:space="preserve">
<value>Required environment variable PROCDUMP_PATH was null or empty. Set PROCDUMP_PATH to path of folder containing appropriate procdump executable.</value>
</data>
<data name="ProcDumpNotGenerated" xml:space="preserve">
<value>CollectDump was enabled but dump file was not generated.</value>
</data>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@
<target state="translated">Bylo povoleno shromáždění výpisu, ale nebyl vygenerován žádný soubor výpisu.</target>
<note />
</trans-unit>
<trans-unit id="BlameParameterKeyIncorrect">
<source>The blame parameter key specified {0} is not valid. Ignoring this key.</source>
<target state="new">The blame parameter key {0} is not valid. Ignoring this parameter.</target>
<note></note>
</trans-unit>
<trans-unit id="BlameParameterValueIncorrect">
<source>The blame parameter key {0} can only support values {1}/{2}. Ignoring this key.</source>
<target state="new">The blame parameter key {0} can only support values {1}/{2}. Ignoring this parameter.</target>
<note></note>
</trans-unit>
<trans-unit id="ProcDumpCouldNotStart">
<source>Could not start process dump: {0}</source>
<target state="new">Could not start process dump: {0}</target>
<note></note>
</trans-unit>
<trans-unit id="ProcDumpNotGenerated">
<source>CollectDump was enabled but dump file was not generated.</source>
<target state="new">CollectDump was enabled but dump file was not generated.</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@
<target state="translated">Die Abbilderfassung war aktiviert, aber es wurde keine Abbilddatei generiert.</target>
<note />
</trans-unit>
<trans-unit id="BlameParameterKeyIncorrect">
<source>The blame parameter key specified {0} is not valid. Ignoring this key.</source>
<target state="new">The blame parameter key {0} is not valid. Ignoring this parameter.</target>
<note></note>
</trans-unit>
<trans-unit id="BlameParameterValueIncorrect">
<source>The blame parameter key {0} can only support values {1}/{2}. Ignoring this key.</source>
<target state="new">The blame parameter key {0} can only support values {1}/{2}. Ignoring this parameter.</target>
<note></note>
</trans-unit>
<trans-unit id="ProcDumpCouldNotStart">
<source>Could not start process dump: {0}</source>
<target state="new">Could not start process dump: {0}</target>
<note></note>
</trans-unit>
<trans-unit id="ProcDumpNotGenerated">
<source>CollectDump was enabled but dump file was not generated.</source>
<target state="new">CollectDump was enabled but dump file was not generated.</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
Loading