8000 Ability to isolate script execution with AssemblyLoadContext by hrumhurum · Pull Request #631 · dotnet-script/dotnet-script · GitHub
[go: up one dir, main page]

Skip to content

Ability to isolate script execution with AssemblyLoadContext #631

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 19 commits into from
Aug 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
f1907e1
AssemblyLoadPal is used instead of AppDomain in order to cover both A…
hrumhurum Aug 18, 2021
79066f1
ScriptRunner can be configured with a custom AssemblyLoadContext.
hrumhurum Aug 19, 2021
11e800c
ScriptRunner refactoring related to AssemblyLoadContext support.
hrumhurum Aug 19, 2021
5b76560
AssemblyLoadContext: assembly loader, downstream propagation via cont…
hrumhurum Aug 19, 2021
a81c8ef
Custom assembly load context can be null and should not be used in t…
hrumhurum Aug 19, 2021
e710739
Gluing and propagating custom AssemblyLoadContext through the higher …
hrumhurum Aug 19, 2021
d8f58a0
Script files are executed in isolated assembly load context.
hrumhurum Aug 19, 2021
aecc8d6
Implemented full assembly isolation support at API level.
hrumhurum Aug 20, 2021
056901d
dotnet-script now uses full assembly isolation for script file execut…
hrumhurum Aug 20, 2021
11a3aa3
Implemented 'ShouldIsolateScriptAssemblies' test for full assembly is…
hrumhurum Aug 20, 2021
68c5645
Fixed library lookup issues with loading of unmanaged DLLs.
hrumhurum Aug 20, 2021
fad86f6
Enabled assembly isolation for interactive script execution.
hrumhurum Aug 20, 2021
436bbe9
Inheritance-friendly ScriptAssemblyLoadContext constructors.
hrumhurum Aug 20, 2021
e6aef47
Removed a no longer needed workaround for the issue #268. Reference t…
hrumhurum Aug 22, 2021
dcc3a89
Removed a no longer needed workaround for the issue #166.
hrumhurum Aug 22, 2021
6a7c2b3
Use a release version of Gapotchenko.FX.Reflection.Loader package.
hrumhurum Aug 22, 2021
2610c6e
Assembly name comparison should be case-insensitive. Fixed internal c…
hrumhurum Aug 22, 2021
b66b500
Merge branch 'master' into gp-feature-a
hrumhurum Aug 23, 2021
353609e
Dropped support for .NET Core 2.1.
hrumhurum Aug 23, 2021
< 8000 strong class="js-file-filter-text css-truncate css-truncate-target" data-target="file-filter.fileFilterActiveText" > 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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -265,3 +265,4 @@ project.json
/build/dotnet-script
/dotnet-script
/.vscode
/src/Dotnet.Script/Properties/launchSettings.json
20 changes: 12 additions & 8 deletions src/Dotnet.Script.Core/Commands/ExecuteCodeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,19 @@ public async Task<TReturn> Execute<TReturn>(ExecuteCodeCommandOptions options)
{
var sourceText = SourceText.From(options.Code);
var context = new ScriptContext(sourceText, options.WorkingDirectory ?? Directory.GetCurrentDirectory(), options.Arguments, null, options.OptimizationLevel, ScriptMode.Eval, options.PackageSources);
var compiler = GetScriptCompiler(!options.NoCache, _logFactory);
var runner = new ScriptRunner(compiler, _logFactory, _scriptConsole);
var compiler = new ScriptCompiler(_logFactory, !options.NoCache)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
var runner = new ScriptRunner(compiler, _logFactory, _scriptConsole)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
return await runner.Execute<TReturn>(context);
}

private static ScriptCompiler GetScriptCompiler(bool useRestoreCache, LogFactory logFactory)
{
var compiler = new ScriptCompiler(logFactory, useRestoreCache);
return compiler;
}
}
}
12 changes: 12 additions & 0 deletions src/Dotnet.Script.Core/Commands/ExecuteCodeCommandOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Microsoft.CodeAnalysis;
#if NETCOREAPP
using System.Runtime.Loader;
#endif

namespace Dotnet.Script.Core.Commands
{
Expand All @@ -20,5 +23,14 @@ public ExecuteCodeCommandOptions(string code, string workingDirectory, string[]
public OptimizationLevel OptimizationLevel { get; }
public bool NoCache { get; }
public string[] PackageSources { get; }

#if NETCOREAPP
#nullable enable
/// <summary>
/// Gets or sets a custom assembly load context to use for script execution.
/// </summary>
public AssemblyLoadContext? AssemblyLoadContext { get; init; }
#nullable restore
#endif
}
}
7 changes: 6 additions & 1 deletion src/Dotnet.Script.Core/Commands/ExecuteInteractiveCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ public ExecuteInteractiveCommand(ScriptConsole scriptConsole, LogFactory logFact

public async Task<int> Execute(ExecuteInteractiveCommandOptions options)
{
var compiler = new ScriptCompiler(_logFactory, useRestoreCache: false);
var compiler = new ScriptCompiler(_logFactory, useRestoreCache: false)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
var runner = new InteractiveRunner(compiler, _logFactory, _scriptConsole, options.PackageSources);

if (options.ScriptFile == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Microsoft.CodeAnalysis;
#if NETCOREAPP
using System.Runtime.Loader;
#endif

namespace Dotnet.Script.Core.Commands
{
public class ExecuteInteractiveCommandOptions
{
public ExecuteInteractiveCommandOptions(ScriptFile scriptFile, string[] arguments ,string[] packageSources)
public ExecuteInteractiveCommandOptions(ScriptFile scriptFile, string[] arguments, string[] packageSources)
{
ScriptFile = scriptFile;
Arguments = arguments;
Expand All @@ -14,5 +16,14 @@ public ExecuteInteractiveCommandOptions(ScriptFile scriptFile, string[] argument
public ScriptFile ScriptFile { get; }
public string[] Arguments { get; }
public string[] PackageSources { get; }

#if NETCOREAPP
#nullable enable
/// <summary>
/// Gets or sets a custom assembly load context to use for script execution.
/// </summary>
public AssemblyLoadContext? AssemblyLoadContext { get; init; }
#nullable restore
#endif
}
}
20 changes: 12 additions & 8 deletions src/Dotnet.Script.Core/Commands/ExecuteLibraryCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,20 @@ public async Task<TReturn> Execute<TReturn>(ExecuteLibraryCommandOptions options
}

var absoluteFilePath = options.LibraryPath.GetRootedPath();
var compiler = GetScriptCompiler(!options.NoCache, _logFactory);
var runner = new ScriptRunner(compiler, _logFactory, _scriptConsole);
var compiler = new ScriptCompiler(_logFactory, !options.NoCache)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
var runner = new ScriptRunner(compiler, _logFactory, _scriptConsole)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
var result = await runner.Execute<TReturn>(absoluteFilePath, options.Arguments);
return result;
9E81 }

private static ScriptCompiler GetScriptCompiler(bool useRestoreCache, LogFactory logFactory)
{
var compiler = new ScriptCompiler(logFactory, useRestoreCache);
return compiler;
}
}
}
13 changes: 13 additions & 0 deletions src/Dotnet.Script.Core/Commands/ExecuteLibraryCommandOptions.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#if NETCOREAPP
using System.Runtime.Loader;
#endif

namespace Dotnet.Script.Core.Commands
{
public class ExecuteLibraryCommandOptions
Expand All @@ -12,5 +16,14 @@ public ExecuteLibraryCommandOptions(string libraryPath, string[] arguments, bool
public string LibraryPath { get; }
public string[] Arguments { get; }
public bool NoCache { get; }

#if NETCOREAPP
#nullable enable
/// <summary>
/// Gets or sets a custom assembly load context to use for script execution.
/// </summary>
public AssemblyLoadContext? AssemblyLoadContext { get; init; }
#nullable restore
#endif
}
}
22 changes: 14 additions & 8 deletions src/Dotnet.Script.Core/Commands/ExecuteScriptCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,14 @@ public async Task<TReturn> Run<TReturn, THost>(ExecuteScriptCommandOptions optio
}

var pathToLibrary = GetLibrary(options);
return await ExecuteLibrary<TReturn>(pathToLibrary, options.Arguments, options.NoCache);

var libraryOptions = new ExecuteLibraryCommandOptions(pathToLibrary, options.Arguments, options.NoCache)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
return await new ExecuteLibraryCommand(_scriptConsole, _logFactory).Execute<TReturn>(libraryOptions);
}

private async Task<TReturn> DownloadAndRunCode<TReturn>(ExecuteScriptCommandOptions executeOptions)
Expand All @@ -57,7 +64,12 @@ private string GetLibrary(ExecuteScriptCommandOptions executeOptions)
return pathToLibrary;
}

var options = new PublishCommandOptions(executeOptions.File, executionCacheFolder, "script", PublishType.Library, executeOptions.OptimizationLevel, executeOptions.PackageSources, null, executeOptions.NoCache);
var options = new PublishCommandOptions(executeOptions.File, executionCacheFolder, "script", PublishType.Library, executeOptions.OptimizationLevel, executeOptions.PackageSources, null, executeOptions.NoCache)
{
#if NETCOREAPP
AssemblyLoadContext = executeOptions.AssemblyLoadContext
#endif
};
new PublishCommand(_scriptConsole, _logFactory).Execute(options);
if (hash != null)
{
Expand Down Expand Up @@ -124,11 +136,5 @@ public bool TryGetHash(string cacheFolder, out string hash)
hash = File.ReadAllText(pathToHashFile);
return true;
}

private async Task<TReturn> ExecuteLibrary<TReturn>(string pathToLibrary, string[] arguments, bool noCache)
{
var options = new ExecuteLibraryCommandOptions(pathToLibrary, arguments, noCache);
return await new ExecuteLibraryCommand(_scriptConsole, _logFactory).Execute<TReturn>(options);
}
}
}
12 changes: 12 additions & 0 deletions src/Dotnet.Script.Core/Commands/ExecuteScriptCommandOptions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
using Microsoft.CodeAnalysis;
#if NETCOREAPP
using System.Runtime.Loader;
#endif

namespace Dotnet.Script.Core.Commands
{
Expand All @@ -20,5 +23,14 @@ public ExecuteScriptCommandOptions(ScriptFile file, string[] arguments, Optimiza
public string[] PackageSources { get; }
public bool IsInteractive { get; }
public bool NoCache { get; }

#if NETCOREAPP
#nullable enable
/// <summary>
/// Gets or sets a custom assembly load context to use for script execution.
/// </summary>
public AssemblyLoadContext? AssemblyLoadContext { get; init; }
#nullable restore
#endif
}
}
14 changes: 6 additions & 8 deletions src/Dotnet.Script.Core/Commands/PublishCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,12 @@ public void Execute(PublishCommandOptions options)
(options.PublishType == PublishType.Library ? Path.Combine(Path.GetDirectoryName(absoluteFilePath), "publish") : Path.Combine(Path.GetDirectoryName(absoluteFilePath), "publish", options.RuntimeIdentifier));

var absolutePublishDirectory = publishDirectory.GetRootedPath();
var compiler = GetScriptCompiler(!options.NoCache, _logFactory);
var compiler = new ScriptCompiler(_logFactory, !options.NoCache)
{
#if NETCOREAPP
AssemblyLoadContext = options.AssemblyLoadContext
#endif
};
var scriptEmitter = new ScriptEmitter(_scriptConsole, compiler);
var publisher = new ScriptPublisher(_logFactory, scriptEmitter);
var code = absoluteFilePath.ToSourceText();
Expand All @@ -43,12 +48,5 @@ public void Execute(PublishCommandOptions options)
publisher.CreateExecutable<int, CommandLineScriptGlobals>(context, _logFactory, options.RuntimeIdentifier, options.LibraryName);
}
}

private static ScriptCompiler GetScriptCompiler(bool useRestoreCache, LogFactory logFactory)
{

var compiler = new ScriptCompiler(logFactory, useRestoreCache);
return compiler;
}
}
}
12 changes: 12 additions & 0 deletions src/Dotnet.Script.Core/Commands/PublishCommandOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using Dotnet.Script.DependencyModel.Environment;
using Microsoft.CodeAnalysis;
#if NETCOREAPP
using System.Runtime.Loader;
#endif

namespace Dotnet.Script.Core.Commands
{
Expand All @@ -25,6 +28,15 @@ public PublishCommandOptions(ScriptFile file, string outputDirectory, string lib
public string[] PackageSources { get; }
public string RuntimeIdentifier { get; }
public bool NoCache { get; }

#if NETCOREAPP
#nullable enable
/// <summary>
/// Gets or sets a custom assembly load context to use for script isolation.
/// </summary>
public AssemblyLoadContext? AssemblyLoadContext { get; init; }
#nullable restore
#endif
}

public enum PublishType
Expand Down
10 changes: 4 additions & 6 deletions src/Dotnet.Script.Core/Dotnet.Script.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Description>A cross platform library allowing you to run C# (CSX) scripts with support for debugging and inline NuGet packages. Based on Roslyn.</Description>
<VersionPrefix>1.2.0</VersionPrefix>
<Authors>filipw</Authors>
<TargetFrameworks>netstandard2.0</TargetFrameworks>
<TargetFrameworks>netstandard2.0;netcoreapp3.1</TargetFrameworks>
<AssemblyName>Dotnet.Script.Core</AssemblyName>
<PackageId>Dotnet.Script.Core</PackageId>
<PackageTags>script;csx;csharp;roslyn</PackageTags>
Expand All @@ -16,24 +16,22 @@
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<LangVersion>9.0</LangVersion>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../dotnet-script.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="**/*.template" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Gapotchenko.FX" Version="2021.1.5" />
<PackageReference Include="Gapotchenko.FX.Reflection.Loader" Version="2021.2.11" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="3.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="ReadLine" Version="2.0.1" />
<PackageReference Include="System.Collections.Immutable" Version="5.0.0" />
<PackageReference Include="System.Reflection.Metadata" Version="5.0.0" />
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<!-- The following references are just quick fixes for issue #166 and issue #268
We need to figure out why we can't load these via the dependency context.
-->
<PackageReference Include="System.Configuration.ConfigurationManager" Version="5.0.0" />
<PackageReference Include="System.Text.Encoding.CodePages" Version="5.0.0" />
<PackageReference Include="StrongNamer" Version="0.2.5" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
Expand Down
Loading
0