in src/Microsoft.TestPlatform.Extensions.BlameDataCollector/BlameCollector.cs [185:294]
private void CollectDumpAndAbortTesthost()
{
_inactivityTimerAlreadyFired = true;
string value;
string unit;
if (_inactivityTimespan.TotalSeconds <= 90)
{
value = ((int)_inactivityTimespan.TotalSeconds).ToString();
unit = Resources.Resources.Seconds;
}
else
{
value = Math.Round(_inactivityTimespan.TotalMinutes, 2).ToString();
unit = Resources.Resources.Minutes;
}
var message = string.Format(CultureInfo.CurrentUICulture, Resources.Resources.InactivityTimeout, value, unit);
EqtTrace.Warning(message);
_logger.LogWarning(_context.SessionDataCollectionContext, message);
try
{
EqtTrace.Verbose("Calling dispose on Inactivity timer.");
_inactivityTimer.Dispose();
}
catch
{
EqtTrace.Verbose("Inactivity timer is already disposed.");
}
if (_collectProcessDumpOnTrigger)
{
// Detach procdump from the testhost process to prevent testhost process from crashing
// if/when we try to kill the existing proc dump process.
// And also prevent collecting dump on exit of the process.
_processDumpUtility.DetachFromTargetProcess(_testHostProcessId);
}
var hangDumpSuccess = false;
try
{
Action<string> logWarning = m => _logger.LogWarning(_context.SessionDataCollectionContext, m);
var dumpDirectory = GetDumpDirectory();
_processDumpUtility.StartHangBasedProcessDump(_testHostProcessId, dumpDirectory, _processFullDumpEnabled, _targetFramework, logWarning);
hangDumpSuccess = true;
}
catch (Exception ex)
{
_logger.LogError(_context.SessionDataCollectionContext, $"Blame: Creating hang dump failed with error.", ex);
}
if (_uploadDumpFiles)
{
try
{
var dumpFiles = _processDumpUtility.GetDumpFiles(true, /* if we killed it by hang dumper, we already have our dump, otherwise it might have crashed, and we want all dumps */ !hangDumpSuccess);
foreach (var dumpFile in dumpFiles)
{
try
{
if (!string.IsNullOrEmpty(dumpFile))
{
var fileTransferInformation = new FileTransferInformation(_context.SessionDataCollectionContext, dumpFile, true, _fileHelper);
_dataCollectionSink.SendFileAsync(fileTransferInformation);
}
}
catch (Exception ex)
{
// Eat up any exception here and log it but proceed with killing the test host process.
EqtTrace.Error(ex);
}
if (!dumpFiles.Any())
{
EqtTrace.Error("BlameCollector.CollectDumpAndAbortTesthost: blame:CollectDumpOnHang was enabled but dump file was not generated.");
}
}
}
catch (Exception ex)
{
_logger.LogError(_context.SessionDataCollectionContext, $"Blame: Collecting hang dump failed with error.", ex);
}
}
else
{
EqtTrace.Info("BlameCollector.CollectDumpAndAbortTesthost: Custom path to dump directory was provided via VSTEST_DUMP_PATH. Skipping attachment upload, the caller is responsible for collecting and uploading the dumps themselves.");
}
try
{
var p = Process.GetProcessById(_testHostProcessId);
try
{
if (!p.HasExited)
{
p.Kill();
}
}
catch (InvalidOperationException)
{
}
}
catch (Exception ex)
{
EqtTrace.Error(ex);
}
}