Files
pgsql-jellyfin/docs/LIBRARYMONITOR_DISPOSAL_FIX_SUMMARY.md
T
wjones 7eb2b445cb Postgres perf, path migration, and shutdown race fixes
- Major query performance boost: replaced correlated subqueries with DistinctBy() in BaseItemRepository, added episode deduplication index, and increased default command timeout to 120s.
- Fixed LibraryMonitor shutdown race: added disposal checks and exception handling in FileRefresher to prevent ObjectDisposedException.
- Added PowerShell and SQL utilities for fixing Linux paths in config files and database; new scripts for WebDir and path migration.
- Auto-fix for WebDir in startup.json on load; new helper scripts and docs.
- Added automated weekly DB performance monitoring scripts and reporting.
- Expanded documentation and README for all fixes, scripts, and migration steps.
- Updated SQL scripts for index creation and diagnostics; improved output handling.
- Updated db-config defaults and added new diagnostic/report files.
2026-03-05 08:56:42 -05:00

2.3 KiB

LibraryMonitor Disposal Fix - Summary

What Was Fixed

Fixed ObjectDisposedException that occurred during application shutdown when file system monitor timer callbacks executed after the service provider was disposed.

Error Message

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'IServiceProvider'.
   at Emby.Server.Implementations.IO.LibraryMonitor: Error processing directory changes

Root Cause

Race condition during shutdown:

  1. Application begins shutdown and disposes IServiceProvider
  2. LibraryMonitor disposal starts
  3. FileRefresher timer callback fires before timer is fully disposed
  4. Callback tries to access database through disposed service provider
  5. Exception thrown

Solution

Added three layers of protection in FileRefresher.cs:

1. Early Exit Check

private void OnTimerCallback(object? state)
{
    if (_disposed) return; // ← Added
    // ...
}

2. Post-Timer-Disposal Check

DisposeTimer();
if (_disposed) return; // ← Added
ProcessPathChanges(paths);

3. Exception Handling

try
{
    itemsToRefresh = paths.Select(GetAffectedBaseItem)...;
}
catch (ObjectDisposedException) // ← Added
{
    _logger.LogDebug("Service provider disposed during shutdown");
    return;
}

Impact

  • Clean application shutdowns
  • No more ObjectDisposedException errors in logs
  • No impact on normal operation
  • Graceful handling of shutdown race conditions

Files Modified

  • Emby.Server.Implementations\IO\FileRefresher.cs
    • Added disposal checks in OnTimerCallback
    • Added disposal handling in ProcessPathChanges

Testing

  • Build successful
  • No breaking changes
  • Addresses shutdown race condition

Documentation

This error typically appears when:

  • Application is shutting down
  • File system changes occur during shutdown
  • Timer callbacks execute after service disposal begins

The fix ensures these scenarios are handled gracefully.


Status: Complete
Risk Level: Low (shutdown-only scenario)
User Impact: Reduced error noise in logs during shutdown