-
Notifications
You must be signed in to change notification settings - Fork 431
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
Address F# Assembly Resolution Issues #893
Closed
Closed
Changes from 1 commit
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
159e37c
add twilio test
dsyme 0d20f6b
function renaming
dsyme 5fbc7ff
add nuget references test
dsyme a0b687e
Address F# Assembly Resolution Issues
sylvanc 2a7090f
delete temporary dll and pdb after compilation
sylvanc f5e81d2
Merge branch 'dsyme-888' into fsharp-assembly-resolve
sylvanc 31e7b3c
Merge branch 'dsyme-891' into fsharp-assembly-resolve
sylvanc d22c965
Update run.csx
dsyme f5aeaf4
Update function.json
dsyme 6e6a926
Update run.csx
dsyme ad90d51
add new tests to csproj
sylvanc b1f21cb
put twilio reference back in run.csx
sylvanc 785a86c
fix file references
sylvanc 40053e2
add function.json for new tests
sylvanc 05093fa
add project.json to NugetChartingReferences
sylvanc 4395106
disabled NugetChartingReferences
sylvanc File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,7 +19,8 @@ public class FunctionAssemblyLoader : IDisposable | |
{ | ||
// Prefix that uniquely identifies our assemblies | ||
// i.e.: "ƒ-<functionname>" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: update (or remove) the comment |
||
public const string AssemblyPrefix = "\u0192-"; | ||
public const string AssemblyPrefix = "f-"; | ||
public const string AssemblySeparator = "__"; | ||
|
||
private readonly ConcurrentDictionary<string, FunctionAssemblyLoadContext> _functionContexts = new ConcurrentDictionary<string, FunctionAssemblyLoadContext>(); | ||
private readonly Regex _functionNameFromAssemblyRegex; | ||
|
@@ -29,7 +30,7 @@ public FunctionAssemblyLoader(string rootScriptPath) | |
{ | ||
_rootScriptUri = new Uri(rootScriptPath, UriKind.RelativeOrAbsolute); | ||
AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; | ||
_functionNameFromAssemblyRegex = new Regex(string.Format(CultureInfo.InvariantCulture, "^{0}(?<name>.*?)#", AssemblyPrefix), RegexOptions.Compiled); | ||
_functionNameFromAssemblyRegex = new Regex(string.Format(CultureInfo.InvariantCulture, "^{0}(?<name>.*?){1}", AssemblyPrefix, AssemblySeparator), RegexOptions.Compiled); | ||
} | ||
|
||
public void Dispose() | ||
|
@@ -51,22 +52,33 @@ internal Assembly ResolveAssembly(object sender, ResolveEventArgs args) | |
FunctionAssemblyLoadContext context = GetFunctionContext(args.RequestingAssembly); | ||
Assembly result = null; | ||
|
||
if (context != null) | ||
try | ||
{ | ||
result = context.ResolveAssembly(args.Name); | ||
} | ||
if (context != null) | ||
{ | ||
result = context.ResolveAssembly(args.Name); | ||
} | ||
|
||
// If we were unable to resolve the assembly, apply the current App Domain policy and attempt to load it. | ||
// This allows us to correctly handle retargetable assemblies, redirects, etc. | ||
if (result == null) | ||
// If we were unable to resolve the assembly, apply the current App Domain policy and attempt to load it. | ||
// This allows us to correctly handle retargetable assemblies, redirects, etc. | ||
if (result == null) | ||
{ | ||
string assemblyName = ((AppDomain)sender).ApplyPolicy(args.Name); | ||
|
||
// If after applying the current policy, we now have a different target assembly name, attempt to load that | ||
// assembly | ||
if (string.Compare(assemblyName, args.Name) != 0) | ||
{ | ||
result = Assembly.Load(assemblyName); | ||
} | ||
} | ||
} | ||
catch (Exception e) | ||
{ | ||
string assemblyName = ((AppDomain)sender).ApplyPolicy(args.Name); | ||
|
||
// If after applying the current policy, we now have a different target assembly name, attempt to load that | ||
// assembly | ||
if (string.Compare(assemblyName, args.Name) != 0) | ||
if (context != null) | ||
{ | ||
result = Assembly.Load(assemblyName); | ||
context.TraceWriter.Warning(string.Format(CultureInfo.InvariantCulture, | ||
"Exception during runtime resolution of assembly '{0}': '{1}'", args.Name, e.ToString())); | ||
} | ||
} | ||
|
||
|
@@ -165,7 +177,7 @@ private FunctionAssemblyLoadContext GetFunctionContext(string functionName) | |
|
||
public static string GetAssemblyNameFromMetadata(FunctionMetadata metadata, string suffix) | ||
{ | ||
return AssemblyPrefix + metadata.Name + "#" + suffix; | ||
return AssemblyPrefix + metadata.Name + AssemblySeparator + suffix.GetHashCode().ToString(); | ||
} | ||
|
||
public string GetFunctionNameFromAssembly(Assembly assembly) | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should remove these files from disk in the
finally
clause.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we truly need to persist those files to disk? I have a feeling you found the issue, which was caused by the assembly name not matching what was expected when looking up the
FunctionAssemblyLoadContext
. If that hasn't been done, it would be worth testing compiling to dynamic assembly, but with the expected assembly name, using theGetAssemblyNameFromMetadata
result above (assuming you can specify the assembly name when compiling to dynamic). With C#, we don't currently persist the assemblies to disk.If that works, we should be able to undo the changes we had to make to the
FunctionAssemblyLoader
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabiocav We would need a new version of FSharp.Compiler.Service for that - one that writes to memory streams. There's a prototype of that around and it's not too hard but it's work.
FCS also checks the in/out file names and assembly names for illegal characters (which seemed reasonable until now - I'm surprised .NET and roslyn don't check these conditions too - but I guess it's legit to use funky characters in assembly names), so we'd need to lift that restriction too in this scenario. There are a couple of other updates to FCS we'd make, such as the list of assembly references implied by F# scripts.
Doing that would take a bit of time so for now it seems easiest to clear the bugs here and do that separately?