Skip to content

Commit 062edad

Browse files
committed
Resetting shared load context during specialization to ensure dependencies are properly resolved
1 parent 0144129 commit 062edad

File tree

5 files changed

+45
-3
lines changed

5 files changed

+45
-3
lines changed

src/WebJobs.Script.WebHost/Standby/IStandbyManager.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
using System;
55
using System.Threading.Tasks;
6-
using Microsoft.Extensions.Primitives;
76

87
namespace Microsoft.Azure.WebJobs.Script.WebHost
98
{

src/WebJobs.Script.WebHost/Standby/StandbyManager.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Threading;
88
using System.Threading.Tasks;
99
using Microsoft.AspNetCore.Hosting;
10+
using Microsoft.Azure.WebJobs.Script.Description;
1011
using Microsoft.Azure.WebJobs.Script.Rpc;
1112
using Microsoft.Azure.WebJobs.Script.WebHost.Properties;
1213
using Microsoft.Extensions.Configuration;
@@ -97,9 +98,14 @@ public async Task SpecializeHostCoreAsync()
9798

9899
_hostNameProvider.Reset();
99100

101+
// Reset the shared load context to ensure we're reloading
102+
// user dependencies
103+
FunctionAssemblyLoadContext.ResetSharedContext();
104+
100105
await _languageWorkerChannelManager.SpecializeAsync();
101106

102107
NotifyChange();
108+
103109
await _scriptHostManager.RestartHostAsync();
104110
await _scriptHostManager.DelayUntilHostReady();
105111
}

src/WebJobs.Script/Description/DotNet/FunctionAssemblyLoadContext.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Reflection;
1010
using System.Runtime.InteropServices;
1111
using System.Runtime.Loader;
12+
using System.Threading;
1213
using Microsoft.Azure.WebJobs.Host;
1314
using Microsoft.Azure.WebJobs.Script.Config;
1415
using Microsoft.Extensions.DependencyModel;
@@ -24,7 +25,8 @@ public partial class FunctionAssemblyLoadContext : AssemblyLoadContext
2425
private static readonly Lazy<Dictionary<string, ScriptRuntimeAssembly>> _runtimeAssemblies = new Lazy<Dictionary<string, ScriptRuntimeAssembly>>(DependencyHelper.GetRuntimeAssemblies);
2526
private static readonly Lazy<Dictionary<string, ResolutionPolicyEvaluator>> _resolutionPolicyEvaluators = new Lazy<Dictionary<string, ResolutionPolicyEvaluator>>(InitializeLoadPolicyEvaluators);
2627
private static readonly ConcurrentDictionary<string, object> _sharedContextAssembliesInFallbackLoad = new ConcurrentDictionary<string, object>();
27-
private static readonly Lazy<FunctionAssemblyLoadContext> _defaultContext = new Lazy<FunctionAssemblyLoadContext>(CreateSharedContext, true);
28+
29+
private static Lazy<FunctionAssemblyLoadContext> _defaultContext = new Lazy<FunctionAssemblyLoadContext>(CreateSharedContext, true);
2830

2931
private readonly List<string> _probingPaths = new List<string>();
3032
private readonly IDictionary<string, string> _depsAssemblies;
@@ -43,6 +45,11 @@ public FunctionAssemblyLoadContext(string basePath)
4345

4446
public static FunctionAssemblyLoadContext Shared => _defaultContext.Value;
4547

48+
internal static void ResetSharedContext()
49+
{
50+
_defaultContext = new Lazy<FunctionAssemblyLoadContext>(CreateSharedContext, true);
51+
}
52+
4653
internal static IDictionary<string, string> InitializeDeps(string basePath)
4754
{
4855
string depsFilePath = Path.Combine(basePath, DotNetConstants.FunctionsDepsFileName);

src/WebJobs.Script/ScriptHostBuilderExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ public static void AddCommonServices(IServiceCollection services)
204204

205205
public static IWebJobsBuilder UseScriptExternalStartup(this IWebJobsBuilder builder, string rootScriptPath, ILoggerFactory loggerFactory, IExtensionBundleManager extensionBundleManager)
206206
{
207-
var logger = loggerFactory.CreateLogger<ScriptStartupTypeLocator>() ?? throw new ArgumentNullException(nameof(loggerFactory));
207+
var logger = loggerFactory?.CreateLogger<ScriptStartupTypeLocator>() ?? throw new ArgumentNullException(nameof(loggerFactory));
208+
208209
return builder.UseExternalStartup(new ScriptStartupTypeLocator(rootScriptPath, logger, extensionBundleManager));
209210
}
210211

test/WebJobs.Script.Tests.Integration/WebHostEndToEnd/SpecializationE2ETests.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Microsoft.Azure.WebJobs.Logging;
1717
using Microsoft.Azure.WebJobs.Logging.ApplicationInsights;
1818
using Microsoft.Azure.WebJobs.Script.Configuration;
19+
using Microsoft.Azure.WebJobs.Script.Description;
1920
using Microsoft.Azure.WebJobs.Script.Rpc;
2021
using Microsoft.Azure.WebJobs.Script.WebHost;
2122
using Microsoft.Extensions.Configuration;
@@ -187,6 +188,34 @@ public async Task Specialization_ThreadUtilization()
187188
}
188189
}
189190

191+
[Fact]
192+
public async Task Specialization_ResetsSharedLoadContext()
193+
{
194+
var builder = CreateStandbyHostBuilder("FunctionExecutionContext");
195+
196+
using (var testServer = new TestServer(builder))
197+
{
198+
var client = testServer.CreateClient();
199+
200+
var response = await client.GetAsync("api/warmup");
201+
response.EnsureSuccessStatusCode();
202+
203+
var placeholderContext = FunctionAssemblyLoadContext.Shared;
204+
205+
_environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteContainerReady, "1");
206+
_environment.SetEnvironmentVariable(EnvironmentSettingNames.AzureWebsitePlaceholderMode, "0");
207+
208+
//await _pauseBeforeHostBuild.WaitAsync(10000);
209+
210+
response = await client.GetAsync("api/functionexecutioncontext");
211+
response.EnsureSuccessStatusCode();
212+
213+
var specializedContext = FunctionAssemblyLoadContext.Shared;
214+
215+
Assert.NotSame(placeholderContext, specializedContext);
216+
}
217+
}
218+
190219
[Fact]
191220
public async Task StartAsync_SetsCorrectActiveHost()
192221
{

0 commit comments

Comments
 (0)