Remove Worker.Core assembly from DOTNET_STARTUP_HOOKS at startup (#1539)

This commit is contained in:
Jacob Viau 2023-05-24 14:57:50 -07:00 коммит произвёл GitHub
Родитель 35e29699bd
Коммит a92c9278b8
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
3 изменённых файлов: 62 добавлений и 2 удалений

Просмотреть файл

@ -10,7 +10,7 @@
### Microsoft.Azure.Functions.Worker.Core <version>
- <event>
- Fixed issue spawning child process while debugging due to "DOTNET_STARTUP_HOOKS" always containing "Microsoft.Azure.Functions.Worker.Core". (#1539)
### Microsoft.Azure.Functions.Worker.Grpc <version>

Просмотреть файл

@ -2,7 +2,10 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
/// <summary>
@ -16,12 +19,17 @@ using System.Threading;
/// </summary>
internal class StartupHook
{
const string StartupHooksEnvVar = "DOTNET_STARTUP_HOOKS";
private static readonly string _startupSeparator = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ";" : ":";
private static readonly string? _assemblyName = typeof(StartupHook).Assembly.GetName().Name;
public static void Initialize()
{
// Time to wait between checks, in ms.
const int SleepTime = 500;
const int MaxWaitCycles = (60 * 1000) / SleepTime;
RemoveSelfFromStartupHooks();
string? debuggerWaitEnabled = Environment.GetEnvironmentVariable("FUNCTIONS_ENABLE_DEBUGGER_WAIT");
string? jsonOutputEnabled = Environment.GetEnvironmentVariable("FUNCTIONS_ENABLE_JSON_OUTPUT");
#if NET5_0_OR_GREATER
@ -62,4 +70,21 @@ internal class StartupHook
}
}
}
internal static void RemoveSelfFromStartupHooks()
{
string? startupHooks = Environment.GetEnvironmentVariable(StartupHooksEnvVar);
if (string.IsNullOrEmpty(startupHooks))
{
// If this call happened, we are clearly part of this environment variable.
// This is mostly to make strict-nulls happy.
return;
}
// netstandard2.0 has no StringSplitOptions overload.
IEnumerable<string> parts = startupHooks.Split(_startupSeparator[0])
.Where(x => !string.Equals(x, _assemblyName, StringComparison.Ordinal));
string newValue = string.Join(_startupSeparator, parts);
Environment.SetEnvironmentVariable(StartupHooksEnvVar, newValue);
}
}

Просмотреть файл

@ -2,7 +2,10 @@
// Licensed under the MIT License. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using Xunit;
namespace Microsoft.Azure.Functions.Worker.Tests
@ -10,7 +13,7 @@ namespace Microsoft.Azure.Functions.Worker.Tests
public class StartupHookTests
{
[Fact]
public void ValidadeHookSetup()
public void ValidateHookSetup()
{
var hookType = typeof(StartupHook);
var initializeMethod = hookType.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public);
@ -24,5 +27,37 @@ namespace Microsoft.Azure.Functions.Worker.Tests
Assert.Empty(initializeMethod.GetParameters());
Assert.Equal(typeof(void), initializeMethod.ReturnType);
}
[Theory]
[InlineData(null)]
[InlineData("Microsoft.Azure.Functions.Worker.Core")]
[InlineData("Some.Other.Assembly")]
[InlineData("Microsoft.Azure.Functions.Worker.Core", "Some.Other.Assembly")]
[InlineData("Some.Other.Assembly", "Microsoft.Azure.Functions.Worker.Core")]
[InlineData("Some.Other.Assembly", "Microsoft.Azure.Functions.Worker.Core", "Another.Assembly")]
public void ValidateHookSetup_HookVariableRemoved(params string[] hooks)
{
hooks ??= Array.Empty<string>();
char separator = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? ';' : ':';
string envVar = "DOTNET_STARTUP_HOOKS";
string original = Environment.GetEnvironmentVariable(envVar);
try
{
IEnumerable<string> expected = hooks.Where(
x => x != typeof(StartupHook).Assembly.GetName().Name);
Environment.SetEnvironmentVariable(envVar, string.Join(separator, hooks));
StartupHook.RemoveSelfFromStartupHooks();
string value = Environment.GetEnvironmentVariable(envVar);
IEnumerable<string> actual = string.IsNullOrEmpty(value)
? Enumerable.Empty<string>() : value.Split(separator);
Assert.Equal(expected, actual);
}
finally
{
Environment.SetEnvironmentVariable(envVar, original);
}
}
}
}