mayuki / Cocona

Micro-framework for .NET console application. Cocona makes it easy and fast to build console applications on .NET.
MIT License
3.22k stars 83 forks source link

The stack overflows when running from a non-writable path #128

Closed DavidL344 closed 2 months ago

DavidL344 commented 6 months ago

When I'm trying to run a command line application built with Cocona, it crashes when its working directory is the file system's root directory (/).

Other directories that aren't writable experience another regression in the form of a longer startup time. For example, running the application from /home/username/Desktop/, or /home/username/Documents/ runs as expected, while running the app from other directories such as /home/, /home/username/, or /proc/ makes it take longer to start.

https://github.com/mayuki/Cocona/assets/69001314/f84ca066-e835-4c11-a4d5-1cf22cc7148d

In the video above, I tried running the app from 3 different directories:

Code to reproduce the issue:

using Cocona;

var builder = CoconaApp.CreateBuilder(); // This line causes the app to crash

var app = builder.Build();

app.AddCommand(() => Console.WriteLine("Hello, World!"));

app.Run();

I believe the stack overflow bug occurs at Cocona.Builder.Internal.BootstrapHostBuilder.cs:49 (the debugger stops stepping over the code there):

configuration.AddConfiguration(hostConfiguration, true);

It might have something to do with Cocona.Builder.Internal.BootstrapHostBuilder.cs:48, where the content root path is set to the working directory (maybe using the running app assembly's location could solve the problem):

// The original line in the Cocona package
configuration.SetBasePath(hostBuilderContext.HostingEnvironment.ContentRootPath);

// The edited line that might fix the issue
configuration.SetBasePath(Path.GetDirectoryName(Assembly.GetCallingAssembly().Location)!);

Please let me know if I can provide any more details to help reproduce the issue. Thank you!

The full error message ``` Stack overflow. Repeat 174379 times: -------------------------------- at System.IO.FileSystemWatcher+RunningInstance+WatchedDirectory.Write(System.Text.StringBuilder, Boolean) -------------------------------- at System.IO.FileSystemWatcher+RunningInstance+WatchedDirectory.GetPath(Boolean, System.String) at System.IO.FileSystemWatcher+RunningInstance.AddDirectoryWatchUnlocked(WatchedDirectory, System.String) at System.IO.FileSystemWatcher+RunningInstance.AddDirectoryWatchUnlocked(WatchedDirectory, System.String) at System.IO.FileSystemWatcher+RunningInstance.AddDirectoryWatchUnlocked(WatchedDirectory, System.String) at System.IO.FileSystemWatcher.StartRaisingEvents() at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.TryEnableFileSystemWatcher() at Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher.CreateFileChangeToken(System.String) at Microsoft.Extensions.FileProviders.PhysicalFileProvider.Watch(System.String) at Microsoft.Extensions.Configuration.FileConfigurationProvider.<.ctor>b__1_0() at Microsoft.Extensions.Primitives.ChangeToken+ChangeTokenRegistration`1[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(System.Func`1, System.Action`1, System.__Canon) at Microsoft.Extensions.Primitives.ChangeToken.OnChange(System.Func`1, System.Action) at Microsoft.Extensions.Configuration.FileConfigurationProvider..ctor(Microsoft.Extensions.Configuration.FileConfigurationSource) at Microsoft.Extensions.Configuration.Json.JsonConfigurationProvider..ctor(Microsoft.Extensions.Configuration.Json.JsonConfigurationSource) at Microsoft.Extensions.Configuration.Json.JsonConfigurationSource.Build(Microsoft.Extensions.Configuration.IConfigurationBuilder) at Microsoft.Extensions.Configuration.ConfigurationManager.AddSource(Microsoft.Extensions.Configuration.IConfigurationSource) at Microsoft.Extensions.Configuration.ConfigurationManager+ConfigurationSources.Add(Microsoft.Extensions.Configuration.IConfigurationSource) at Microsoft.Extensions.Configuration.ConfigurationManager.Microsoft.Extensions.Configuration.IConfigurationBuilder.Add(Microsoft.Extensions.Configuration.IConfigurationSource) at Microsoft.Extensions.Configuration.ConfigurationExtensions.Add[[System.__Canon, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Microsoft.Extensions.Configuration.IConfigurationBuilder, System.Action`1) at Microsoft.Extensions.Configuration.JsonConfigurationExtensions.AddJsonFile(Microsoft.Extensions.Configuration.IConfigurationBuilder, System.Action`1) at Microsoft.Extensions.Configuration.JsonConfigurationExtensions.AddJsonFile(Microsoft.Extensions.Configuration.IConfigurationBuilder, Microsoft.Extensions.FileProviders.IFileProvider, System.String, Boolean, Boolean) at Microsoft.Extensions.Configuration.JsonConfigurationExtensions.AddJsonFile(Microsoft.Extensions.Configuration.IConfigurationBuilder, System.String, Boolean, Boolean) at Microsoft.Extensions.Hosting.HostingHostBuilderExtensions+<>c__DisplayClass11_0.b__1(Microsoft.Extensions.Hosting.HostBuilderContext, Microsoft.Extensions.Configuration.IConfigurationBuilder) at Cocona.Builder.Internal.BootstrapHostBuilder.Apply(Microsoft.Extensions.Configuration.ConfigurationManager, Microsoft.Extensions.Hosting.HostBuilder) at Cocona.Builder.CoconaAppBuilder..ctor(System.String[], System.Action`1) at Cocona.CoconaApp.CreateBuilder(System.String[], System.Action`1) at Program.
$(System.String[]) ```