Skip to content

Commit 9fb8b40

Browse files
authored
function timeout now disposes of WebHost services (#5593)
1 parent ce3cda9 commit 9fb8b40

27 files changed

+211
-175
lines changed

src/WebJobs.Script.WebHost/DependencyInjection/WebHostServiceProvider.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace Microsoft.Azure.WebJobs.Script.WebHost.DependencyInjection
1010
{
11-
public class WebHostServiceProvider : IServiceProvider, IServiceScopeFactory
11+
public class WebHostServiceProvider : IServiceProvider, IServiceScopeFactory, IDisposable
1212
{
1313
private static readonly Rules _defaultContainerRules;
1414
private readonly Container _container;
@@ -50,5 +50,10 @@ public IServiceScope CreateScope()
5050
{
5151
return new JobHostServiceScope(_container.OpenScope(preferInterpretation: _container.PreferInterpretation));
5252
}
53+
54+
public void Dispose()
55+
{
56+
_container?.Dispose();
57+
}
5358
}
5459
}

src/WebJobs.Script.WebHost/Diagnostics/MetricsEventManager.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
using Microsoft.Azure.WebJobs.Script.Description;
1313
using Microsoft.Azure.WebJobs.Script.Diagnostics;
1414
using Microsoft.Azure.WebJobs.Script.WebHost.ContainerManagement;
15-
using Microsoft.Azure.WebJobs.Script.WebHost.Management;
1615
using Microsoft.Azure.WebJobs.Script.WebHost.Metrics;
1716
using Microsoft.Azure.WebJobs.Script.WebHost.Models;
1817
using Microsoft.Extensions.Logging;
@@ -32,11 +31,14 @@ public class MetricsEventManager : IDisposable
3231
private readonly object _functionActivityTrackerLockObject = new object();
3332
private readonly IMetricsPublisher _metricsPublisher;
3433
private readonly ILinuxContainerActivityPublisher _linuxContainerActivityPublisher;
34+
private readonly ILogger<MetricsEventManager> _logger;
3535
private bool _disposed;
3636
private IOptionsMonitor<AppServiceOptions> _appServiceOptions;
3737

38-
public MetricsEventManager(IOptionsMonitor<AppServiceOptions> appServiceOptions, IEventGenerator generator, int functionActivityFlushIntervalSeconds, IMetricsPublisher metricsPublisher, ILinuxContainerActivityPublisher linuxContainerActivityPublisher, int metricsFlushIntervalMS = DefaultFlushIntervalMS)
38+
public MetricsEventManager(IOptionsMonitor<AppServiceOptions> appServiceOptions, IEventGenerator generator, int functionActivityFlushIntervalSeconds, IMetricsPublisher metricsPublisher, ILinuxContainerActivityPublisher linuxContainerActivityPublisher, ILogger<MetricsEventManager> logger, int metricsFlushIntervalMS = DefaultFlushIntervalMS)
3939
{
40+
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
41+
4042
// we read these in the ctor (not static ctor) since it can change on the fly
4143
_appServiceOptions = appServiceOptions;
4244
_eventGenerator = generator;
@@ -303,6 +305,15 @@ protected internal virtual void WriteMetricEvents(SystemMetricEvent[] metricEven
303305

304306
protected virtual void Dispose(bool disposing)
305307
{
308+
try
309+
{
310+
_logger.LogDebug($"Disposing {nameof(MetricsEventManager)}");
311+
}
312+
catch
313+
{
314+
// Best effort logging.
315+
}
316+
306317
if (!_disposed)
307318
{
308319
if (disposing)

src/WebJobs.Script.WebHost/Diagnostics/WebHostMetricsLogger.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using Microsoft.Azure.WebJobs.Script.Diagnostics;
77
using Microsoft.Azure.WebJobs.Script.WebHost.ContainerManagement;
88
using Microsoft.Azure.WebJobs.Script.WebHost.Metrics;
9+
using Microsoft.Extensions.Logging;
910
using Microsoft.Extensions.Options;
1011

1112
namespace Microsoft.Azure.WebJobs.Script.WebHost.Diagnostics
@@ -15,8 +16,8 @@ public class WebHostMetricsLogger : IMetricsLogger, IDisposable
1516
private readonly MetricsEventManager _metricsEventManager;
1617
private bool disposed = false;
1718

18-
public WebHostMetricsLogger(IOptionsMonitor<AppServiceOptions> appServiceOptions, IEventGenerator eventGenerator, IMetricsPublisher metricsPublisher, ILinuxContainerActivityPublisher linuxContainerActivityPublisher)
19-
: this(appServiceOptions, eventGenerator, metricsPublisher, linuxContainerActivityPublisher, 5)
19+
public WebHostMetricsLogger(IOptionsMonitor<AppServiceOptions> appServiceOptions, IEventGenerator eventGenerator, IMetricsPublisher metricsPublisher, ILinuxContainerActivityPublisher linuxContainerActivityPublisher, ILoggerFactory loggerFactory)
20+
: this(appServiceOptions, eventGenerator, metricsPublisher, linuxContainerActivityPublisher, 5, loggerFactory)
2021
{
2122
}
2223

@@ -25,9 +26,9 @@ public WebHostMetricsLogger(MetricsEventManager eventManager)
2526
_metricsEventManager = eventManager;
2627
}
2728

28-
protected WebHostMetricsLogger(IOptionsMonitor<AppServiceOptions> appServiceOptions, IEventGenerator eventGenerator, IMetricsPublisher metricsPublisher, ILinuxContainerActivityPublisher linuxContainerActivityPublisher, int metricEventIntervalInSeconds)
29+
protected WebHostMetricsLogger(IOptionsMonitor<AppServiceOptions> appServiceOptions, IEventGenerator eventGenerator, IMetricsPublisher metricsPublisher, ILinuxContainerActivityPublisher linuxContainerActivityPublisher, int metricEventIntervalInSeconds, ILoggerFactory loggerFactory)
2930
{
30-
_metricsEventManager = new MetricsEventManager(appServiceOptions, eventGenerator, metricEventIntervalInSeconds, metricsPublisher, linuxContainerActivityPublisher);
31+
_metricsEventManager = new MetricsEventManager(appServiceOptions, eventGenerator, metricEventIntervalInSeconds, metricsPublisher, linuxContainerActivityPublisher, loggerFactory.CreateLogger<MetricsEventManager>());
3132
}
3233

3334
public object BeginEvent(string eventName, string functionName = null, string data = null)

src/WebJobs.Script.WebHost/FileMonitoringService.cs

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
using Microsoft.Extensions.Hosting;
1818
using Microsoft.Extensions.Logging;
1919
using Microsoft.Extensions.Options;
20+
using IApplicationLifetime = Microsoft.AspNetCore.Hosting.IApplicationLifetime;
2021

2122
namespace Microsoft.Azure.WebJobs.Script.WebHost
2223
{
@@ -28,6 +29,7 @@ public class FileMonitoringService : IHostedService, IDisposable
2829
private readonly IScriptHostManager _scriptHostManager;
2930
private readonly string _hostLogPath;
3031
private readonly ILogger _logger;
32+
private readonly ILogger<FileMonitoringService> _typedLogger;
3133
private readonly IList<IDisposable> _eventSubscriptions = new List<IDisposable>();
3234
private readonly Func<Task> _restart;
3335
private readonly Action _shutdown;
@@ -38,6 +40,8 @@ public class FileMonitoringService : IHostedService, IDisposable
3840
private bool _shutdownScheduled;
3941
private int _restartRequested;
4042
private bool _disposed = false;
43+
private bool _watchersStopped = false;
44+
private object _stopWatchersLock = new object();
4145

4246
public FileMonitoringService(IOptions<ScriptJobHostOptions> scriptOptions, ILoggerFactory loggerFactory, IScriptEventManager eventManager, IApplicationLifetime applicationLifetime, IScriptHostManager scriptHostManager)
4347
{
@@ -48,6 +52,9 @@ public FileMonitoringService(IOptions<ScriptJobHostOptions> scriptOptions, ILogg
4852
_hostLogPath = Path.Combine(_scriptOptions.RootLogPath, "Host");
4953
_logger = loggerFactory.CreateLogger(LogCategories.Startup);
5054

55+
// Use this for newer logs as we can't change existing categories of log messages
56+
_typedLogger = loggerFactory.CreateLogger<FileMonitoringService>();
57+
5158
// If a file change should result in a restart, we debounce the event to
5259
// ensure that only a single restart is triggered within a specific time window.
5360
// This allows us to deal with a large set of file change events that might
@@ -85,6 +92,7 @@ public Task StartAsync(CancellationToken cancellationToken)
8592

8693
public Task StopAsync(CancellationToken cancellationToken)
8794
{
95+
StopFileWatchers();
8896
return Task.CompletedTask;
8997
}
9098

@@ -120,6 +128,40 @@ private void InitializeFileWatchers()
120128
TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously)));
121129
}
122130

131+
private void StopFileWatchers()
132+
{
133+
lock (_stopWatchersLock)
134+
{
135+
if (_watchersStopped)
136+
{
137+
return;
138+
}
139+
140+
_typedLogger.LogDebug("Stopping file watchers.");
141+
142+
_fileEventSource?.Dispose();
143+
144+
if (_debugModeFileWatcher != null)
145+
{
146+
_debugModeFileWatcher.Changed -= OnDebugModeFileChanged;
147+
_debugModeFileWatcher.Dispose();
148+
}
149+
150+
if (_diagnosticModeFileWatcher != null)
151+
{
152+
_diagnosticModeFileWatcher.Changed -= OnDiagnosticModeFileChanged;
153+
_diagnosticModeFileWatcher.Dispose();
154+
}
155+
156+
foreach (var subscription in _eventSubscriptions)
157+
{
158+
subscription.Dispose();
159+
}
160+
161+
_watchersStopped = true;
162+
}
163+
}
164+
123165
/// <summary>
124166
/// Whenever the debug sentinel file changes we update our debug timeout
125167
/// </summary>
@@ -264,24 +306,7 @@ protected virtual void Dispose(bool disposing)
264306
{
265307
if (disposing)
266308
{
267-
_fileEventSource?.Dispose();
268-
269-
if (_debugModeFileWatcher != null)
270-
{
271-
_debugModeFileWatcher.Changed -= OnDebugModeFileChanged;
272-
_debugModeFileWatcher.Dispose();
273-
}
274-
275-
if (_diagnosticModeFileWatcher != null)
276-
{
277-
_diagnosticModeFileWatcher.Changed -= OnDiagnosticModeFileChanged;
278-
_diagnosticModeFileWatcher.Dispose();
279-
}
280-
281-
foreach (var subscription in _eventSubscriptions)
282-
{
283-
subscription.Dispose();
284-
}
309+
StopFileWatchers();
285310
}
286311

287312
_disposed = true;

src/WebJobs.Script.WebHost/WebJobsScriptHostService.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using Microsoft.Extensions.Hosting;
2020
using Microsoft.Extensions.Logging;
2121
using Microsoft.Extensions.Options;
22+
using IApplicationLifetime = Microsoft.AspNetCore.Hosting.IApplicationLifetime;
2223

2324
namespace Microsoft.Azure.WebJobs.Script.WebHost
2425
{
@@ -52,7 +53,7 @@ public class WebJobsScriptHostService : IHostedService, IScriptHostManager, ISer
5253

5354
public WebJobsScriptHostService(IOptionsMonitor<ScriptApplicationHostOptions> applicationHostOptions, IScriptHostBuilder scriptHostBuilder, ILoggerFactory loggerFactory,
5455
IServiceScopeFactory rootScopeFactory, IScriptWebHostEnvironment scriptWebHostEnvironment, IEnvironment environment,
55-
HostPerformanceManager hostPerformanceManager, IOptions<HostHealthMonitorOptions> healthMonitorOptions, IMetricsLogger metricsLogger, IApplicationLifetime applicationLifetime)
56+
HostPerformanceManager hostPerformanceManager, IOptions<HostHealthMonitorOptions> healthMonitorOptions, IMetricsLogger metricsLogger, IApplicationLifetime applicationLifetime)
5657
{
5758
if (loggerFactory == null)
5859
{

src/WebJobs.Script.WebHost/WebScriptHostExceptionHandler.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
using System;
55
using System.Runtime.ExceptionServices;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Hosting;
78
using Microsoft.Azure.WebJobs.Host;
89
using Microsoft.Azure.WebJobs.Host.Timers;
9-
using Microsoft.Extensions.Hosting;
1010
using Microsoft.Extensions.Logging;
1111

1212
namespace Microsoft.Azure.WebJobs.Script.WebHost

src/WebJobs.Script/Description/Workers/Http/HttpFunctionDescriptorProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22
// Licensed under the MIT License. See License.txt in the project root for license information.
33

44
using System.Collections.Generic;
5+
using Microsoft.AspNetCore.Hosting;
56
using Microsoft.Azure.WebJobs.Script.Extensibility;
67
using Microsoft.Azure.WebJobs.Script.Workers;
7-
using Microsoft.Extensions.Hosting;
88
using Microsoft.Extensions.Logging;
99

1010
namespace Microsoft.Azure.WebJobs.Script.Description

src/WebJobs.Script/Description/Workers/Rpc/RpcFunctionDescriptorProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Threading.Tasks;
7+
using Microsoft.AspNetCore.Hosting;
78
using Microsoft.Azure.WebJobs.Script.Extensibility;
89
using Microsoft.Azure.WebJobs.Script.Workers;
9-
using Microsoft.Extensions.Hosting;
1010
using Microsoft.Extensions.Logging;
1111

1212
namespace Microsoft.Azure.WebJobs.Script.Description

src/WebJobs.Script/Description/Workers/WorkerFunctionDescriptorProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
using System.Reflection;
99
using System.Reflection.Emit;
1010
using System.Threading.Tasks;
11+
using Microsoft.AspNetCore.Hosting;
1112
using Microsoft.Azure.WebJobs.Description;
1213
using Microsoft.Azure.WebJobs.Script.Binding;
1314
using Microsoft.Azure.WebJobs.Script.Extensibility;
1415
using Microsoft.Azure.WebJobs.Script.Workers;
15-
using Microsoft.Extensions.Hosting;
1616
using Microsoft.Extensions.Logging;
1717

1818
namespace Microsoft.Azure.WebJobs.Script.Description

src/WebJobs.Script/Description/Workers/WorkerFunctionInvoker.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
using System.Reactive.Linq;
1111
using System.Threading;
1212
using System.Threading.Tasks;
13+
using Microsoft.AspNetCore.Hosting;
1314
using Microsoft.Azure.WebJobs.Script.Binding;
1415
using Microsoft.Azure.WebJobs.Script.Workers;
1516
using Microsoft.CodeAnalysis;
16-
using Microsoft.Extensions.Hosting;
1717
using Microsoft.Extensions.Logging;
1818
using Newtonsoft.Json.Linq;
1919

0 commit comments

Comments
 (0)