From aa2edb76d241c1083a7b4e9d2e429b902df54836 Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Thu, 2 Mar 2017 17:38:37 -0800 Subject: [PATCH] Allow Directory Creation failures to continue for Service Account use scenarios that don't have home directories Removed redundant checks if saving to analysis cache Updated test to avoid race condition where a module is added in between checks addresses https://github.com/PowerShell/PowerShell/issues/3011 Removed unnecessary check to save to disk --- .../CoreCLR/CorePsPlatform.cs | 36 ++++++++++++++++--- .../engine/Modules/AnalysisCache.cs | 17 +++++++-- test/powershell/Host/ConsoleHost.Tests.ps1 | 22 ++++++++++++ 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs index 62f84e8545f..e9960a2abe5 100644 --- a/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs +++ b/src/System.Management.Automation/CoreCLR/CorePsPlatform.cs @@ -261,7 +261,14 @@ public static string SelectProductNameForDirectory(Platform.XDG_Type dirpath) // create the xdg folder if needed if (!Directory.Exists(xdgDataHomeDefault)) { - Directory.CreateDirectory(xdgDataHomeDefault); + try + { + Directory.CreateDirectory(xdgDataHomeDefault); + } + catch (UnauthorizedAccessException) + { + //service accounts won't have permission to create user folder + } } return xdgDataHomeDefault; } @@ -277,7 +284,14 @@ public static string SelectProductNameForDirectory(Platform.XDG_Type dirpath) //xdg values have not been set if (!Directory.Exists(xdgModuleDefault)) //module folder not always guaranteed to exist { - Directory.CreateDirectory(xdgModuleDefault); + try + { + Directory.CreateDirectory(xdgModuleDefault); + } + catch (UnauthorizedAccessException) + { + //service accounts won't have permission to create user folder + } } return xdgModuleDefault; } @@ -296,7 +310,14 @@ public static string SelectProductNameForDirectory(Platform.XDG_Type dirpath) //xdg values have not been set if (!Directory.Exists(xdgCacheDefault)) //module folder not always guaranteed to exist { - Directory.CreateDirectory(xdgCacheDefault); + try + { + Directory.CreateDirectory(xdgCacheDefault); + } + catch (UnauthorizedAccessException) + { + //service accounts won't have permission to create user folder + } } return xdgCacheDefault; @@ -306,7 +327,14 @@ public static string SelectProductNameForDirectory(Platform.XDG_Type dirpath) { if (!Directory.Exists(Path.Combine(xdgcachehome, "powershell"))) { - Directory.CreateDirectory(Path.Combine(xdgcachehome, "powershell")); + try + { + Directory.CreateDirectory(Path.Combine(xdgcachehome, "powershell")); + } + catch (UnauthorizedAccessException) + { + //service accounts won't have permission to create user folder + } } return Path.Combine(xdgcachehome, "powershell"); diff --git a/src/System.Management.Automation/engine/Modules/AnalysisCache.cs b/src/System.Management.Automation/engine/Modules/AnalysisCache.cs index 3e626f5402d..19809589557 100644 --- a/src/System.Management.Automation/engine/Modules/AnalysisCache.cs +++ b/src/System.Management.Automation/engine/Modules/AnalysisCache.cs @@ -618,6 +618,8 @@ private static byte[] GetHeader() private int _saveCacheToDiskQueued; + private bool _saveCacheToDisk = true; + public void QueueSerialization() { // We expect many modules to rapidly call for serialization. @@ -625,7 +627,7 @@ public void QueueSerialization() // after it seems like we've stopped adding stuff to write out. This is // avoids blocking the pipeline thread waiting for the write to finish. // We want to make sure we only queue one task. - if (Interlocked.Increment(ref _saveCacheToDiskQueued) == 1) + if (_saveCacheToDisk && Interlocked.Increment(ref _saveCacheToDiskQueued) == 1) { Task.Run(async delegate { @@ -694,6 +696,8 @@ private static void Write(string val, byte[] bytes, FileStream stream) private void Serialize(string filename) { AnalysisCacheData fromOtherProcess = null; + Diagnostics.Assert(_saveCacheToDisk != false, "Serialize should never be called without going through QueueSerialization which has a check"); + try { if (Utils.NativeFileExists(filename)) @@ -710,7 +714,16 @@ private void Serialize(string filename) var folder = Path.GetDirectoryName(filename); if (!Directory.Exists(folder)) { - Directory.CreateDirectory(folder); + try + { + Directory.CreateDirectory(folder); + } + catch (UnauthorizedAccessException) + { + // service accounts won't be able to create directory + _saveCacheToDisk = false; + return; + } } } } diff --git a/test/powershell/Host/ConsoleHost.Tests.ps1 b/test/powershell/Host/ConsoleHost.Tests.ps1 index 531187fc77e..434a1dba993 100644 --- a/test/powershell/Host/ConsoleHost.Tests.ps1 +++ b/test/powershell/Host/ConsoleHost.Tests.ps1 @@ -381,6 +381,28 @@ foo } } } + + Context "Data, Config, and Cache locations" { + BeforeEach { + $XDG_CACHE_HOME = $env:XDG_CACHE_HOME + $XDG_DATA_HOME = $env:XDG_DATA_HOME + $XDG_CONFIG_HOME = $env:XDG_CONFIG_HOME + } + + AfterEach { + $env:XDG_CACHE_HOME = $XDG_CACHE_HOME + $env:XDG_DATA_HOME = $XDG_DATA_HOME + $env:XDG_CONFIG_HOME = $XDG_CONFIG_HOME + } + + It "Should start if Data, Config, and Cache location is not accessible" -skip:($IsWindows) { + $env:XDG_CACHE_HOME = "/dev/cpu" + $env:XDG_DATA_HOME = "/dev/cpu" + $env:XDG_CONFIG_HOME = "/dev/cpu" + $output = & powershell -noprofile -Command { (get-command).count } + [int]$output | Should BeGreaterThan 0 + } + } } Describe "Console host api tests" -Tag CI {