Skip to content
Merged
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
79 changes: 16 additions & 63 deletions src/System.Management.Automation/engine/hostifaces/LocalPipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ namespace System.Management.Automation.Runspaces
/// </summary>
internal sealed class LocalPipeline : PipelineBase
{
// Each OS platform uses different default stack size for threads:
// - Windows 2 MB
// - Linux 8 Mb
// - MacOs 512 KB
// We should use the same stack size for pipeline threads on all platforms to get predictable behavior.
// The stack size we use for pipeline threads is 10MB, which is inherited from Windows PowerShell.
internal const int DefaultPipelineStackSize = 10_000_000;

#region constructors

/// <summary>
Expand Down Expand Up @@ -149,17 +157,11 @@ protected override void StartPipelineExecution()
case PSThreadOptions.Default:
case PSThreadOptions.UseNewThread:
{
#if CORECLR
//Start execution of pipeline in another thread
// No ApartmentState/ThreadStackSize In CoreCLR
Thread invokeThread = new Thread(new ThreadStart(this.InvokeThreadProc));
SetupInvokeThread(invokeThread, true);
#else
//Start execution of pipeline in another thread
// 2004/05/02-JonN Specify maxStack parameter
Thread invokeThread = new Thread(new ThreadStart(this.InvokeThreadProc), MaxStack);
// Start execution of pipeline in another thread
Thread invokeThread = new Thread(new ThreadStart(this.InvokeThreadProc), DefaultPipelineStackSize);
SetupInvokeThread(invokeThread, true);

#if !CORECLR
// No ApartmentState in CoreCLR
ApartmentState apartmentState;

if (InvocationSettings != null && InvocationSettings.ApartmentState != ApartmentState.Unknown)
Expand Down Expand Up @@ -245,55 +247,6 @@ private void SetupInvokeThread(Thread invokeThread, bool changeName)
}
}

#if !CORECLR
/// <summary>
/// Stack Reserve setting for pipeline threads
/// </summary>
internal static int MaxStack
{
get
{
int i = ReadRegistryInt("PipelineMaxStackSizeMB", 10);
if (i < 10)
i = 10; // minimum 10MB
else if (i > 100)
i = 100; // maximum 100MB
return i * 1000000;
}
}

internal static int ReadRegistryInt(string policyValueName, int defaultValue)
{
RegistryKey key;
try
{
key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\PowerShell\\1\\ShellIds");
}
catch (System.Security.SecurityException)
{
return defaultValue;
}
if (null == key)
return defaultValue;

object temp;
try
{
temp = key.GetValue(policyValueName);
}
catch (System.Security.SecurityException)
{
return defaultValue;
}
if (!(temp is int))
{
return defaultValue;
}
int i = (int)temp;
return i;
}
#endif

///<summary>
/// Helper method for asynchronous invoke
///<returns>Unhandled FlowControl exception if InvocationSettings.ExposeFlowControlExceptions is true.</returns>
Expand Down Expand Up @@ -1219,25 +1172,25 @@ protected override
}

/// <summary>
/// Helper class that holds the thread used to execute pipelines when CreateThreadOptions.ReuseThread is used
/// Helper class that holds the thread used to execute pipelines when CreateThreadOptions.ReuseThread is used.
/// </summary>
internal class PipelineThread : IDisposable
{
/// <summary>
/// Creates the worker thread and waits for it to be ready
/// Creates the worker thread and waits for it to be ready.
/// </summary>
#if CORECLR
internal PipelineThread()
{
_worker = new Thread(WorkerProc);
_worker = new Thread(WorkerProc, LocalPipeline.DefaultPipelineStackSize);
_workItem = null;
_workItemReady = new AutoResetEvent(false);
_closed = false;
}
#else
internal PipelineThread(ApartmentState apartmentState)
{
_worker = new Thread(WorkerProc, LocalPipeline.MaxStack);
_worker = new Thread(WorkerProc, LocalPipeline.DefaultPipelineStackSize);
_workItem = null;
_workItemReady = new AutoResetEvent(false);
_closed = false;
Expand Down