Skip to content

ServiceProvider is never disposed - PLC teardown code is unreachable in production #112

Description

@mrcsin

Summary

Program.StartupAsync builds the container (Program.cs, services.BuildServiceProvider()) and nothing ever disposes it — there is no desktop.ShutdownRequested/Exit hook and App.Run does not dispose the provider after StartWithClassicDesktopLifetime returns.

Impact

The carefully written teardown paths never run in production (only tests exercise them):

  • S7Service.DisposeAsync — graceful PLC disconnect;
  • PlcLifecycleManager.Dispose — sync-ownership lease release;
  • PlcSyncCoordinator.Dispose — waits out a pending sync.

Concretely: a recipe edit debounced in the last second before exit is silently dropped; the ownership lock-file handle is released by the OS, not by the code that owns it; the PLC sees a TCP reset instead of a clean disconnect.

Suggested fix

Dispose the provider after StartWithClassicDesktopLifetime returns (async disposables via DisposeAsync), or hook IClassicDesktopStyleApplicationLifetime.ShutdownRequested. Verify the shutdown order tolerates the PLC being unreachable (teardown must not block exit — bound it with a timeout).

Related: singleton view models (MainWindowViewModel, RecipeCoordinator) also implement IDisposable and are equally unreachable; container disposal covers them for free.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions