Skip to content

Stack overflow in FileSystemWatcher when running as systemd service #113855

Open
@StephenCleary

Description

@StephenCleary

Description

.NET 9 app will fail to start when running as a systemd service; this appears to be a problem with FileSystemWatcher (for watching the json config files).

Reproduction Steps

Within WSL:

mkdir SystemdRepro && cd SystemdRepro
dotnet new worker
dotnet add package Microsoft.Extensions.Hosting.Systemd
dotnet build

Then create the file repro.service with the following content (you will need to adjust the User and ExecStart lines):

[Unit]
Description=repro
After=network.target
StartLimitIntervalSec=0

[Service]
Type=simple
User=stephen
ExecStart=/mnt/d/Code/SystemdRepro/bin/Debug/net9.0/SystemdRepro

[Install]
WantedBy=multi-user.target

Then start the service and observe the logs:

sudo cp repro.service /etc/systemd/system && sudo systemctl daemon-reload
sudo systemctl start repro.service
journalctl -u repro.service -o cat | cat

Expected behavior

Service does not crash.

Actual behavior

Service crashes with these logs:

Started repro.service - repro.
Stack overflow.
Repeated 174575 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+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=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]..ctor(System.Func`1<Microsoft.Extensions.Primitives.IChangeToken>, System.Action`1<System.__Canon>, System.__Canon)
   at Microsoft.Extensions.Primitives.ChangeToken.OnChange(System.Func`1<Microsoft.Extensions.Primitives.IChangeToken>, 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=9.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](Microsoft.Extensions.Configuration.IConfigurationBuilder, System.Action`1<System.__Canon>)
   at Microsoft.Extensions.Configuration.JsonConfigurationExtensions.AddJsonFile(Microsoft.Extensions.Configuration.IConfigurationBuilder, System.Action`1<Microsoft.Extensions.Configuration.Json.JsonConfigurationSource>)
   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.ApplyDefaultAppConfiguration(Microsoft.Extensions.Hosting.HostBuilderContext, Microsoft.Extensions.Configuration.IConfigurationBuilder, System.String[])
   at Microsoft.Extensions.Hosting.HostApplicationBuilder..ctor(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings)
   at Microsoft.Extensions.Hosting.HostApplicationBuilder..ctor(System.String[])
   at Microsoft.Extensions.Hosting.Host.CreateApplicationBuilder(System.String[])
   at Program.<Main>$(System.String[])
repro.service: Main process exited, code=dumped, status=6/ABRT
repro.service: Failed with result 'core-dump'.

Regression?

No response

Known Workarounds

Disable reload-on-config-change:

var config = new ConfigurationManager();
config.AddInMemoryCollection(new Dictionary<string, string?>() { ["hostBuilder:reloadConfigOnChange"] = "false" });
var builder = Host.CreateApplicationBuilder(new HostApplicationBuilderSettings
{
	Args = args,
	Configuration = config,
});

Configuration

(within WSL):

$ dotnet --version
9.0.104
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 24.04.2 LTS
Release:        24.04
Codename:       noble

Architecture: x64

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions