From 02d8fbedfc0838152015846a720e5607ee5dcb00 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 7 Nov 2023 16:31:21 -0800 Subject: [PATCH 1/2] Updates to handle self-contained application load. --- .../FunctionsNetHost/AppLoader/AppLoader.cs | 63 +++++++++++-------- .../src/FunctionsNetHost/AppLoader/NetHost.cs | 18 ++++-- 2 files changed, 52 insertions(+), 29 deletions(-) diff --git a/host/src/FunctionsNetHost/AppLoader/AppLoader.cs b/host/src/FunctionsNetHost/AppLoader/AppLoader.cs index 639ce9200..14f38c8c6 100644 --- a/host/src/FunctionsNetHost/AppLoader/AppLoader.cs +++ b/host/src/FunctionsNetHost/AppLoader/AppLoader.cs @@ -1,10 +1,16 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System.Diagnostics; using System.Runtime.InteropServices; namespace FunctionsNetHost { + // If having problems with the managed host, enable the following: + // Environment.SetEnvironmentVariable("COREHOST_TRACE", "1"); + // In Unix environment, you need to run the below command in the terminal to set the environment variable. + // export COREHOST_TRACE=1 + /// /// Manages loading hostfxr & worker assembly. /// @@ -14,37 +20,35 @@ internal sealed class AppLoader : IDisposable private IntPtr _hostContextHandle = IntPtr.Zero; private bool _disposed; - internal AppLoader() - { - LoadHostfxrLibrary(); - } - - private void LoadHostfxrLibrary() - { - // If having problems with the managed host, enable the following: - // Environment.SetEnvironmentVariable("COREHOST_TRACE", "1"); - // In Unix environment, you need to run the below command in the terminal to set the environment variable. - // export COREHOST_TRACE=1 - - var hostfxrFullPath = NetHost.GetHostFxrPath(); - Logger.LogTrace($"hostfxr path:{hostfxrFullPath}"); - - _hostfxrHandle = NativeLibrary.Load(hostfxrFullPath); - if (_hostfxrHandle == IntPtr.Zero) - { - Logger.Log($"Failed to load hostfxr. hostfxr path:{hostfxrFullPath}"); - return; - } - - Logger.LogTrace($"hostfxr library loaded successfully."); - } - internal int RunApplication(string? assemblyPath) { ArgumentNullException.ThrowIfNull(assemblyPath, nameof(assemblyPath)); unsafe { + var parameters = new NetHost.get_hostfxr_parameters + { + size = sizeof(NetHost.get_hostfxr_parameters), + assembly_path = GetCharArrayPointer(assemblyPath) + }; + + var sw = Stopwatch.StartNew(); + var hostfxrFullPath = NetHost.GetHostFxrPath(¶meters); + sw.Stop(); + Logger.LogTrace($"hostfxr path:{hostfxrFullPath}. get_hostfxr_path took {sw.ElapsedMilliseconds}ms"); + + sw.Restart(); + _hostfxrHandle = NativeLibrary.Load(hostfxrFullPath); + sw.Stop(); + + if (_hostfxrHandle == IntPtr.Zero) + { + Logger.Log($"Failed to load hostfxr. hostfxrFullPath:{hostfxrFullPath}"); + return -1; + } + + Logger.LogTrace($"hostfxr loaded in {sw.ElapsedMilliseconds}ms"); + var error = HostFxr.Initialize(1, new[] { assemblyPath }, IntPtr.Zero, out _hostContextHandle); if (_hostContextHandle == IntPtr.Zero) @@ -98,5 +102,14 @@ private void Dispose(bool disposing) _disposed = true; } } + + private static unsafe char* GetCharArrayPointer(string assemblyPath) + { +#if OS_LINUX + return (char*)Marshal.StringToHGlobalAnsi(assemblyPath).ToPointer(); +#else + return (char*)Marshal.StringToHGlobalUni(assemblyPath).ToPointer(); +#endif + } } } diff --git a/host/src/FunctionsNetHost/AppLoader/NetHost.cs b/host/src/FunctionsNetHost/AppLoader/NetHost.cs index 61397c29f..3a7d70207 100644 --- a/host/src/FunctionsNetHost/AppLoader/NetHost.cs +++ b/host/src/FunctionsNetHost/AppLoader/NetHost.cs @@ -7,18 +7,28 @@ namespace FunctionsNetHost { internal class NetHost { + public unsafe struct get_hostfxr_parameters + { + public nint size; + + // Optional.Path to the application assembly, + // If specified, hostfxr is located from this directory if present (For self-contained deployments) + public char* assembly_path; + public char* dotnet_root; + } + [DllImport("nethost", CharSet = CharSet.Auto)] - private static extern int get_hostfxr_path( + private unsafe static extern int get_hostfxr_path( [Out] char[] buffer, [In] ref int buffer_size, - IntPtr reserved); + get_hostfxr_parameters* parameters); - internal static string GetHostFxrPath() + internal unsafe static string GetHostFxrPath(get_hostfxr_parameters* parameters) { char[] buffer = new char[200]; int bufferSize = buffer.Length; - int rc = get_hostfxr_path(buffer, ref bufferSize, IntPtr.Zero); + int rc = get_hostfxr_path(buffer, ref bufferSize, parameters); if (rc != 0) { From 4d54ce0740b1168344da601ab1d4e0c43bf0d8c9 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 7 Nov 2023 17:54:20 -0800 Subject: [PATCH 2/2] Removing stopwatch instrumentation. --- .../src/FunctionsNetHost/AppLoader/AppLoader.cs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/host/src/FunctionsNetHost/AppLoader/AppLoader.cs b/host/src/FunctionsNetHost/AppLoader/AppLoader.cs index 14f38c8c6..c09eba28f 100644 --- a/host/src/FunctionsNetHost/AppLoader/AppLoader.cs +++ b/host/src/FunctionsNetHost/AppLoader/AppLoader.cs @@ -32,29 +32,24 @@ internal int RunApplication(string? assemblyPath) assembly_path = GetCharArrayPointer(assemblyPath) }; - var sw = Stopwatch.StartNew(); var hostfxrFullPath = NetHost.GetHostFxrPath(¶meters); - sw.Stop(); - Logger.LogTrace($"hostfxr path:{hostfxrFullPath}. get_hostfxr_path took {sw.ElapsedMilliseconds}ms"); - - sw.Restart(); + Logger.LogTrace($"hostfxr path:{hostfxrFullPath}"); + _hostfxrHandle = NativeLibrary.Load(hostfxrFullPath); - sw.Stop(); if (_hostfxrHandle == IntPtr.Zero) { Logger.Log($"Failed to load hostfxr. hostfxrFullPath:{hostfxrFullPath}"); return -1; } - - Logger.LogTrace($"hostfxr loaded in {sw.ElapsedMilliseconds}ms"); + + Logger.LogTrace($"hostfxr loaded."); var error = HostFxr.Initialize(1, new[] { assemblyPath }, IntPtr.Zero, out _hostContextHandle); if (_hostContextHandle == IntPtr.Zero) { - Logger.Log( - $"Failed to initialize the .NET Core runtime. Assembly path:{assemblyPath}"); + Logger.Log($"Failed to initialize the .NET Core runtime. Assembly path:{assemblyPath}"); return -1; } @@ -103,7 +98,7 @@ private void Dispose(bool disposing) } } - private static unsafe char* GetCharArrayPointer(string assemblyPath) + private static unsafe char* GetCharArrayPointer(string assemblyPath) { #if OS_LINUX return (char*)Marshal.StringToHGlobalAnsi(assemblyPath).ToPointer();