dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.21k stars 4.72k forks source link

Hot reload breaks child process starts #58000

Closed ppekrol closed 3 years ago

ppekrol commented 3 years ago

Hi all,

I'm using .NET SDK '6.0.100-preview.7.21379.14' on Windows 10 x64 with following code:

    public class Program
    {
        public static void Main(string[] args)
        {
            EmbeddedServer.Instance.StartServer(new ServerOptions()
            {
                DataDirectory = "./localRavenDB",
                ServerUrl = "http://127.0.0.1:8080"
            });

            using (var store = EmbeddedServer.Instance.GetDocumentStore("DB1"))
            {
                Console.WriteLine("OK");
                Console.ReadLine();
            }
        }
    }

and CSPROJ as follows:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="RavenDB.Embedded" Version="5.2.1" />
  </ItemGroup>

</Project>

It works fine when I do dotnet build or dotnet run via the CLI, but I'm having issues starting this via VS2022 (prev 3.1).

Getting following error:

Unhandled exception. System.InvalidOperationException: Unable to start the RavenDB Server
Error:
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at System.Reflection.RuntimeAssembly.GetType(QCallAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive, ObjectHandleOnStack assemblyLoadContext)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at System.Reflection.Assembly.GetType(String name, Boolean throwOnError)
   at System.StartupHookProvider.CallStartupHook(StartupHookNameOrPath startupHook)
   at System.StartupHookProvider.ProcessStartupHooks()

   at Raven.Embedded.EmbeddedServer.RunServer() in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 299
   at Raven.Embedded.EmbeddedServer.GetServerUriAsync(CancellationToken token) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 185
   at Raven.Embedded.EmbeddedServer.<>c__DisplayClass13_0.<<GetDocumentStoreAsync>b__0>d.MoveNext() in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 143
--- End of stack trace from previous location ---
   at Raven.Embedded.EmbeddedServer.GetDocumentStoreAsync(DatabaseOptions options, CancellationToken token) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 161
   at Raven.Client.Util.AsyncHelpers.RunSync[T](Func`1 task) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Client\Util\AsyncHelpers.cs:line 91
   at Raven.Embedded.EmbeddedServer.GetDocumentStore(String database) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 114
   at ConsoleApp4.Program.Main(String[] args) in D:\workspaces\Temp\ConsoleApp4\ConsoleApp4\Program.cs:line 15

Please note that RavenDB Embedded issues Process.Start underneath and has no dependency on .NET 6 (requires .NET 5.0.7). Code here: https://github.com/ravendb/ravendb/blob/e96640ba52d81b86842abedfa6ec7a9db30eb24b/src/Raven.Embedded/RavenServerRunner.cs#L77

We already submitted that issue to VS team (https://developercommunity.visualstudio.com/t/Project-Execution-Issue-with-VS-2022/1496825), but they say that this is RavenDB problem hence I'm writing here. I do not believe that it is and I'm not sure how to solve this.

Would appreciate your help.

dotnet-issue-labeler[bot] commented 3 years ago

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

Symbai commented 3 years ago

Has it worked on .NET 5? If not you should try. Also why did you removed the extra information from the exception? https://github.com/ravendb/ravendb/blob/e96640ba52d81b86842abedfa6ec7a9db30eb24b/src/Raven.Embedded/RavenServerRunner.cs#L100-L102 and why didn't you contacted the authors of RavenDB first because it fails in their code?

ppekrol commented 3 years ago

It works fine in VS2019 and I am one of the authors of RavenDB.

I just do not understand why starting a process that does not depend on .NET 6 yields that exception, but only if compiled from inside VS2022. When compiled from VS2019 or CLI, works fine. From me it looks like VS2022 is injecting sth there.

ppekrol commented 3 years ago

Simpler repro. No dependencies. No RavenDB.

From CLI:

dotnet build -c Release
cd .\ConsoleToSchedule
dotnet run -c Release

Output:
Starting 'D:\workspaces\Temp\ConsoleApp4\ConsoleToStart\bin\Release\net5.0\ConsoleToStart.exe'.
OK

From VS2022:

Open SLN
Rebuild in Release
Set as Startup: ConsoleToSchedule
Run

Output:
Starting 'D:\workspaces\Temp\ConsoleApp4\ConsoleToStart\bin\Release\net5.0\ConsoleToStart.exe'.
OK
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
   at System.Reflection.RuntimeAssembly.GetType(QCallAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive, ObjectHandleOnStack assemblyLoadContext)
   at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   at System.Reflection.Assembly.GetType(String name, Boolean throwOnError)
   at System.StartupHookProvider.CallStartupHook(StartupHookNameOrPath startupHook)
   at System.StartupHookProvider.ProcessStartupHooks()

D:\workspaces\Temp\ConsoleApp4\ConsoleToSchedule\bin\Release\net6.0\ConsoleToSchedule.exe (process 21916) exited with code -532462766.
Press any key to close this window . . .

Attached the repro. ProcessStartRepro.zip

hez2010 commented 3 years ago

You need to set the working directory for the process.

ppekrol commented 3 years ago

Changed code to:

using System.Diagnostics;

var path = Path.GetFullPath($"{AppContext.BaseDirectory}/../../../../ConsoleToStart/bin/Release/net5.0/ConsoleToStart.exe");
var workingDir = Path.GetDirectoryName(path);

Console.WriteLine($"Starting '{path}' with working directory '{workingDir}'.");

Process.Start(new ProcessStartInfo
{
    FileName = path,
    WorkingDirectory = workingDir
});

Console.WriteLine("OK");

Still does not work.

Symbai commented 3 years ago

Attached the repro. ProcessStartRepro.zip

I cannot reproduce it, works fine for me using VS 2022. Must be something on your end. image

jkotas commented 3 years ago

VS2022 is setting DOTNET_STARTUP_HOOKS environment variable to "c:\program files\microsoft visual studio\2022\preview\common7\ide\commonextensions\microsoft\hotreload\Microsoft.Extensions.DotNetDeltaApplier.dll" that is .NET 6 targeting assembly. DOTNET_STARTUP_HOOKS gets inherited by the child processes. If the child process targets older .NET versions, the startup hook loading will fail with the error above.

This is a bug in hot reload.

ghost commented 3 years ago

Tagging subscribers to this area: @tommcdon See info in area-owners.md if you want to be subscribed.

Issue Details
Hi all, I'm using .NET SDK '6.0.100-preview.7.21379.14' on Windows 10 x64 with following code: ``` public class Program { public static void Main(string[] args) { EmbeddedServer.Instance.StartServer(new ServerOptions() { DataDirectory = "./localRavenDB", ServerUrl = "http://127.0.0.1:8080" }); using (var store = EmbeddedServer.Instance.GetDocumentStore("DB1")) { Console.WriteLine("OK"); Console.ReadLine(); } } } ``` and CSPROJ as follows: ``` Exe net6.0 ``` It works fine when I do `dotnet build` or `dotnet run` via the CLI, but I'm having issues starting this via VS2022 (prev 3.1). Getting following error: ``` Unhandled exception. System.InvalidOperationException: Unable to start the RavenDB Server Error: Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. File name: 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' at System.Reflection.RuntimeAssembly.GetType(QCallAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type, ObjectHandleOnStack keepAlive, ObjectHandleOnStack assemblyLoadContext) at System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase) at System.Reflection.Assembly.GetType(String name, Boolean throwOnError) at System.StartupHookProvider.CallStartupHook(StartupHookNameOrPath startupHook) at System.StartupHookProvider.ProcessStartupHooks() at Raven.Embedded.EmbeddedServer.RunServer() in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 299 at Raven.Embedded.EmbeddedServer.GetServerUriAsync(CancellationToken token) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 185 at Raven.Embedded.EmbeddedServer.<>c__DisplayClass13_0.<b__0>d.MoveNext() in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 143 --- End of stack trace from previous location --- at Raven.Embedded.EmbeddedServer.GetDocumentStoreAsync(DatabaseOptions options, CancellationToken token) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 161 at Raven.Client.Util.AsyncHelpers.RunSync[T](Func`1 task) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Client\Util\AsyncHelpers.cs:line 91 at Raven.Embedded.EmbeddedServer.GetDocumentStore(String database) in C:\Builds\RavenDB-Stable-5.2\52001\src\Raven.Embedded\EmbeddedServer.cs:line 114 at ConsoleApp4.Program.Main(String[] args) in D:\workspaces\Temp\ConsoleApp4\ConsoleApp4\Program.cs:line 15 ``` Please note that RavenDB Embedded issues Process.Start underneath and has no dependency on .NET 6 (requires .NET 5.0.7). Code here: https://github.com/ravendb/ravendb/blob/e96640ba52d81b86842abedfa6ec7a9db30eb24b/src/Raven.Embedded/RavenServerRunner.cs#L77 We already submitted that issue to VS team (https://developercommunity.visualstudio.com/t/Project-Execution-Issue-with-VS-2022/1496825), but they say that this is RavenDB problem hence I'm writing here. I do not believe that it is and I'm not sure how to solve this. Would appreciate your help.
Author: ppekrol
Assignees: -
Labels: `area-Diagnostics-coreclr`, `untriaged`
Milestone: -
jkotas commented 3 years ago

cc @mikem8361

mikem8361 commented 3 years ago

I'm not sure how the runtime itself can fix this?

jkotas commented 3 years ago

Agree. This issue should be transfer to its proper home. The hot reload helper .dll needs to target least common denominator TFM; or reload needs to clear the env variable; or the reload helper .dll needs to be loaded using funceval without setting the startup hook env variables.

tommcdon commented 3 years ago

Adding @pranavkm

pranavkm commented 3 years ago

The reload helper is gated on a TFM, but it doesn't stop from leaking into child processes. We can definitely clear the environment variable that would be a fairly targeted / self-contained change.