From 104b62ffd073b1296ac0ca6ba0e264cd8b1ba937 Mon Sep 17 00:00:00 2001 From: hrumhurum Date: Thu, 26 Aug 2021 19:10:09 +0300 Subject: [PATCH 1/3] Assembly isolation is opt-in at dotnet-script level. --- .../ScriptExecutionTests.cs | 2 +- src/Dotnet.Script/Program.cs | 27 ++++++++++--------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/Dotnet.Script.Tests/ScriptExecutionTests.cs b/src/Dotnet.Script.Tests/ScriptExecutionTests.cs index 112403b4..4eaf9c4f 100644 --- a/src/Dotnet.Script.Tests/ScriptExecutionTests.cs +++ b/src/Dotnet.Script.Tests/ScriptExecutionTests.cs @@ -475,7 +475,7 @@ public void ShouldIgnoreGlobalJsonInScriptFolder() [Fact] public void ShouldIsolateScriptAssemblies() { - var result = ScriptTestRunner.Default.ExecuteFixture("Isolation"); + var result = ScriptTestRunner.Default.ExecuteFixture("Isolation", "--isolated-load-context"); Assert.Contains("10.0.0.0", result.output); } diff --git a/src/Dotnet.Script/Program.cs b/src/Dotnet.Script/Program.cs index a12cb30b..c599b6b9 100644 --- a/src/Dotnet.Script/Program.cs +++ b/src/Dotnet.Script/Program.cs @@ -67,10 +67,11 @@ private static int Wain(string[] args) var debugMode = app.Option(DebugFlagShort + " | " + DebugFlagLong, "Enables debug output.", CommandOptionType.NoValue); var verbosity = app.Option("--verbosity", " Set the verbosity level of the command. Allowed values are t[trace], d[ebug], i[nfo], w[arning], e[rror], and c[ritical].", CommandOptionType.SingleValue); var nocache = app.Option("--no-cache", "Disable caching (Restore and Dll cache)", CommandOptionType.NoValue); + var isolatedLoadContext = app.Option("--isolated-load-context", "Use isolated assembly load context", CommandOptionType.NoValue); var infoOption = app.Option("--info", "Displays environmental information", CommandOptionType.NoValue); var argsBeforeDoubleHyphen = args.TakeWhile(a => a != "--").ToArray(); - var argsAfterDoubleHyphen = args.SkipWhile(a => a != "--").Skip(1).ToArray(); + var argsAfterDoubleHyphen = args.SkipWhile(a => a != "--").Skip(1).ToArray(); const string helpOptionTemplate = "-? | -h | --help"; app.HelpOption(helpOptionTemplate); @@ -99,7 +100,7 @@ private static int Wain(string[] args) } var logFactory = CreateLogFactory(verbosity.Value(), debugMode.HasValue()); - var options = new ExecuteCodeCommandOptions(source, cwd.Value(), app.RemainingArguments.Concat(argsAfterDoubleHyphen).ToArray(),configuration.ValueEquals("release", StringComparison.OrdinalIgnoreCase) ? OptimizationLevel.Release : OptimizationLevel.Debug, nocache.HasValue(),packageSources.Values?.ToArray()); + var options = new ExecuteCodeCommandOptions(source, cwd.Value(), app.RemainingArguments.Concat(argsAfterDoubleHyphen).ToArray(), configuration.ValueEquals("release", StringComparison.OrdinalIgnoreCase) ? OptimizationLevel.Release : OptimizationLevel.Debug, nocache.HasValue(), packageSources.Values?.ToArray()); return await new ExecuteCodeCommand(ScriptConsole.Default, logFactory).Execute(options); }); }); @@ -231,11 +232,15 @@ private static int Wain(string[] args) return 0; } + AssemblyLoadContext assemblyLoadContext = null; + if (isolatedLoadContext.HasValue()) + assemblyLoadContext = new ScriptAssemblyLoadContext(); + if (scriptFile.HasValue) { if (interactive.HasValue()) { - return await RunInteractiveWithSeed(file.Value, logFactory, scriptArguments, packageSources.Values?.ToArray()); + return await RunInteractiveWithSeed(file.Value, logFactory, scriptArguments, packageSources.Values?.ToArray(), assemblyLoadContext); } var fileCommandOptions = new ExecuteScriptCommandOptions @@ -248,15 +253,15 @@ private static int Wain(string[] args) nocache.HasValue() ) { - AssemblyLoadContext = CreateAssemblyLoadContext() + AssemblyLoadContext = assemblyLoadContext }; var fileCommand = new ExecuteScriptCommand(ScriptConsole.Default, logFactory); return await fileCommand.Run(fileCommandOptions); - } + } else { - await RunInteractive(!nocache.HasValue(), logFactory, packageSources.Values?.ToArray()); + await RunInteractive(!nocache.HasValue(), logFactory, packageSources.Values?.ToArray(), assemblyLoadContext); } return exitCode; }); @@ -264,26 +269,24 @@ private static int Wain(string[] args) return app.Execute(argsBeforeDoubleHyphen); } - private static async Task RunInteractive(bool useRestoreCache, LogFactory logFactory, string[] packageSources) + private static async Task RunInteractive(bool useRestoreCache, LogFactory logFactory, string[] packageSources, AssemblyLoadContext assemblyLoadContext) { var options = new ExecuteInteractiveCommandOptions(null, Array.Empty(), packageSources) { - AssemblyLoadContext = CreateAssemblyLoadContext() + AssemblyLoadContext = assemblyLoadContext }; await new ExecuteInteractiveCommand(ScriptConsole.Default, logFactory).Execute(options); return 0; } - private async static Task RunInteractiveWithSeed(string file, LogFactory logFactory, string[] arguments, string[] packageSources) + private async static Task RunInteractiveWithSeed(string file, LogFactory logFactory, string[] arguments, string[] packageSources, AssemblyLoadContext assemblyLoadContext) { var options = new ExecuteInteractiveCommandOptions(new ScriptFile(file), arguments, packageSources) { - AssemblyLoadContext = CreateAssemblyLoadContext() + AssemblyLoadContext = assemblyLoadContext }; await new ExecuteInteractiveCommand(ScriptConsole.Default, logFactory).Execute(options); return 0; } - - static AssemblyLoadContext CreateAssemblyLoadContext() => new ScriptAssemblyLoadContext(); } } From e4197b682028bb995670433e2d53beaf4a103599 Mon Sep 17 00:00:00 2001 From: hrumhurum Date: Thu, 26 Aug 2021 19:18:45 +0300 Subject: [PATCH 2/3] Added test for AssemblyLoadContext.CurrentContextualReflectionContext in assembly-isolated mode. --- src/Dotnet.Script.Core/ScriptRunner.cs | 2 -- src/Dotnet.Script.Tests/ScriptExecutionTests.cs | 7 +++++++ .../CurrentContextualReflectionContext.csx | 4 ++++ 3 files changed, 11 insertions(+), 2 deletions(-) create mode 100644 src/Dotnet.Script.Tests/TestFixtures/CurrentContextualReflectionContext/CurrentContextualReflectionContext.csx diff --git a/src/Dotnet.Script.Core/ScriptRunner.cs b/src/Dotnet.Script.Core/ScriptRunner.cs index b154d054..66b605fe 100644 --- a/src/Dotnet.Script.Core/ScriptRunner.cs +++ b/src/Dotnet.Script.Core/ScriptRunner.cs @@ -85,9 +85,7 @@ IntPtr OnLoadingUnmanagedDll(ScriptAssemblyLoadContext sender, ScriptAssemblyLoa scriptAssemblyLoadContext.Loading += OnLoading; scriptAssemblyLoadContext.LoadingUnmanagedDll += OnLoadingUnmanagedDll; } -#endif -#if NETCOREAPP3_0_OR_GREATER using var contextualReflectionScope = assemblyLoadContext != null ? assemblyLoadContext.EnterContextualReflection() : default; #endif diff --git a/src/Dotnet.Script.Tests/ScriptExecutionTests.cs b/src/Dotnet.Script.Tests/ScriptExecutionTests.cs index 4eaf9c4f..0dee4c2e 100644 --- a/src/Dotnet.Script.Tests/ScriptExecutionTests.cs +++ b/src/Dotnet.Script.Tests/ScriptExecutionTests.cs @@ -479,6 +479,13 @@ public void ShouldIsolateScriptAssemblies() Assert.Contains("10.0.0.0", result.output); } + [Fact] + public void ShouldSetCurrentContextualReflectionContext() + { + var result = ScriptTestRunner.Default.ExecuteFixture("CurrentContextualReflectionContext", "--isolated-load-context"); + Assert.Contains("Dotnet.Script.Core.ScriptAssemblyLoadContext", result.output); + } + private static string CreateTestScript(string scriptFolder) { string script = @" diff --git a/src/Dotnet.Script.Tests/TestFixtures/CurrentContextualReflectionContext/CurrentContextualReflectionContext.csx b/src/Dotnet.Script.Tests/TestFixtures/CurrentContextualReflectionContext/CurrentContextualReflectionContext.csx new file mode 100644 index 00000000..e7e2420e --- /dev/null +++ b/src/Dotnet.Script.Tests/TestFixtures/CurrentContextualReflectionContext/CurrentContextualReflectionContext.csx @@ -0,0 +1,4 @@ +using System.Runtime.Loader; + +var context = AssemblyLoadContext.CurrentContextualReflectionContext; +Console.WriteLine(context?.ToString() ?? ""); From ca5eb325d9a33591d0315f091eef67c0da972302 Mon Sep 17 00:00:00 2001 From: hrumhurum Date: Thu, 26 Aug 2021 19:21:53 +0300 Subject: [PATCH 3/3] Re-added workarounds for issues #166 and #268 because assembly isolation is opt-in. --- src/Dotnet.Script.Core/Dotnet.Script.Core.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Dotnet.Script.Core/Dotnet.Script.Core.csproj b/src/Dotnet.Script.Core/Dotnet.Script.Core.csproj index a58748f6..645e237c 100644 --- a/src/Dotnet.Script.Core/Dotnet.Script.Core.csproj +++ b/src/Dotnet.Script.Core/Dotnet.Script.Core.csproj @@ -32,6 +32,10 @@ + + + +