Skip to content

Commit

Permalink
Iron out the test failures
Browse files Browse the repository at this point in the history
  • Loading branch information
daxian-dbw committed Apr 7, 2021
1 parent caf86e5 commit e90ebbb
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 46 deletions.
4 changes: 2 additions & 2 deletions src/System.Management.Automation/engine/MshCommandRuntime.cs
Expand Up @@ -3732,7 +3732,7 @@ internal void SetVariableListsInPipe()
{
Diagnostics.Assert(_thisCommand is PSScriptCmdlet, "this is only done for script cmdlets");

if (_outVarList != null && !OutputPipe.NullPipe)
if (_outVarList != null && !OutputPipe.IgnoreOutVariableList)
{
// A null pipe is used when executing the 'Clean' block of a PSScriptCmdlet.
// In such a case, we don't capture output to the out variable list.
Expand Down Expand Up @@ -3775,7 +3775,7 @@ internal void RemoveVariableListsInPipe()
{
// Diagnostics.Assert(thisCommand is PSScriptCmdlet, "this is only done for script cmdlets");

if (_outVarList != null)
if (_outVarList != null && !OutputPipe.IgnoreOutVariableList)
{
this.OutputPipe.RemoveVariableList(VariableStreamKind.Output, _outVarList);
}
Expand Down
5 changes: 5 additions & 0 deletions src/System.Management.Automation/engine/Pipe.cs
Expand Up @@ -109,6 +109,11 @@ public override string ToString()
/// </summary>
internal int OutBufferCount { get; set; } = 0;

/// <summary>
/// Gets whether the out variable list should be ignored.
/// </summary>
internal bool IgnoreOutVariableList { get; set; }

/// <summary>
/// If true, then all input added to this pipe will simply be discarded...
/// </summary>
Expand Down
88 changes: 46 additions & 42 deletions src/System.Management.Automation/engine/pipeline.cs
Expand Up @@ -7,7 +7,6 @@
using System.Management.Automation.Tracing;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using Microsoft.PowerShell.Telemetry;

using Dbg = System.Management.Automation.Diagnostics;
Expand Down Expand Up @@ -539,11 +538,8 @@ internal Array SynchronousExecuteEnumerate(object input)
// the call to 'pipelineProcessor.Step'.
// It's possible (though very unlikely) that the call to 'pipelineProcessor.Step' failed with an
// exception, and in such case, the 'pipelineProcessor' would have been disposed, and therefore
// we should skip the 'DoComplete' call on it.
if (!redirectPipelineProcessor._stopping)
{
redirectPipelineProcessor.DoCompleteCore(null);
}
// the call to 'DoComplete' will simply return, because '_commands' was already set to null.
redirectPipelineProcessor.DoCompleteCore(null);
}
}

Expand Down Expand Up @@ -584,6 +580,10 @@ private void DoCompleteCore(CommandProcessorBase commandRequestingUpstreamComman
{
if (_commands is null)
{
// This could happen to a redirection pipeline, either for an expression (e.g. 1 > a.txt)
// or for a command (e.g. command > a.txt).
// An exception may be thrown from the call to 'StartStepping' or 'Step' on the pipeline,
// which causes the pipeline commands to be disposed.
return;
}

Expand Down Expand Up @@ -657,13 +657,6 @@ private void DoCompleteCore(CommandProcessorBase commandRequestingUpstreamComman
lastCommandRuntime.PipelineProcessor.LogPipelineComplete();
}
}

// If a terminating error occurred, report it now.
if (_firstTerminatingError != null)
{
this.LogExecutionException(_firstTerminatingError.SourceException);
_firstTerminatingError.Throw();
}
}

/// <summary>
Expand Down Expand Up @@ -732,42 +725,44 @@ private void Clean()
/// <returns>The results of the execution.</returns>
internal Array DoComplete()
{
if (Stopping)
try
{
throw new PipelineStoppedException();
}
if (Stopping)
{
throw new PipelineStoppedException();
}

if (!_executionStarted)
{
throw PSTraceSource.NewInvalidOperationException(
PipelineStrings.PipelineNotStarted);
}
if (!_executionStarted)
{
throw PSTraceSource.NewInvalidOperationException(
PipelineStrings.PipelineNotStarted);
}

ExceptionDispatchInfo toRethrowInfo;
try
{
DoCompleteCore(null);
ExceptionDispatchInfo toRethrowInfo;
try
{
DoCompleteCore(null);
return RetrieveResults();
}
catch (RuntimeException e)
{
toRethrowInfo = GetFirstError(e);
}

return RetrieveResults();
}
catch (RuntimeException e)
{
toRethrowInfo = GetFirstError(e);
// By rethrowing the exception outside of the handler, we allow the CLR on X64/IA64 to free from the stack
// the exception records related to this exception.

// The only reason we should get here is if an exception should be rethrown.
Diagnostics.Assert(toRethrowInfo != null, "Alternate protocol path failure");
toRethrowInfo.Throw();

// UNREACHABLE
return null;
}
finally
{
DisposeCommands();
}

// By rethrowing the exception outside of the handler,
// we allow the CLR on X64/IA64 to free from the stack
// the exception records related to this exception.

// The only reason we should get here is if
// an exception should be rethrown.
Diagnostics.Assert(toRethrowInfo != null, "Alternate protocol path failure");
toRethrowInfo.Throw();
return null; // UNREACHABLE
}

/// <summary>
Expand Down Expand Up @@ -1193,6 +1188,14 @@ private void Inject(object input, bool enumerate)
/// </returns>
private Array RetrieveResults()
{
if (_commands is null)
{
// This could happen to an expression redirection pipeline (e.g. 1 > a.txt).
// An exception may be thrown from the call to 'StartStepping' or 'Step' on the pipeline,
// which causes the pipeline commands to be disposed.
return MshCommandRuntime.StaticEmptyArray;
}

// If the error queue has been linked, it's up to the link to
// deal with the output. Don't do anything here...
if (!_linkedErrorOutput)
Expand All @@ -1214,17 +1217,17 @@ private Array RetrieveResults()
// If the success queue has been linked, it's up to the link to
// deal with the output. Don't do anything here...
if (_linkedSuccessOutput)
{
return MshCommandRuntime.StaticEmptyArray;
}

CommandProcessorBase LastCommandProcessor = _commands[_commands.Count - 1];
ValidateCommandProcessorNotNull(LastCommandProcessor, errorMessage: null);

Array results = LastCommandProcessor.CommandRuntime.GetResultsAsArray();

// 2003/10/02-JonN
// Do not return the same results more than once
LastCommandProcessor.CommandRuntime.OutputPipe.Clear();

return results is null ? MshCommandRuntime.StaticEmptyArray : results;
}

Expand Down Expand Up @@ -1288,6 +1291,7 @@ private void DisposeCommands()
// If Dispose throws an exception, record it as a pipeline failure and continue disposing cmdlets.
try
{
commandProcessor.CommandRuntime.RemoveVariableListsInPipe();
commandProcessor.Dispose();
}
// The only vaguely plausible reason for a failure here is an exception in Command.Dispose.
Expand Down
Expand Up @@ -2319,9 +2319,15 @@ internal override void DoCleanResource()
{
if (_scriptBlock.HasCleanupBlock && _anyClauseExecuted)
{
// The 'Clean' block doesn't write to pipeline.
// The 'Clean' block doesn't write any output to pipeline, so we use a 'NullPipe' here and
// disallow the output to be collected by an 'out' variable. However, the error, warning,
// and information records should still be collectable by the corresponding variables.
Pipe oldOutputPipe = _commandRuntime.OutputPipe;
_functionContext._outputPipe = _commandRuntime.OutputPipe = new Pipe { NullPipe = true };
_functionContext._outputPipe = _commandRuntime.OutputPipe = new Pipe
{
NullPipe = true,
IgnoreOutVariableList = true,
};

try
{
Expand Down

0 comments on commit e90ebbb

Please sign in to comment.