7eb2b445cb
- 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.
95 lines
2.3 KiB
Markdown
95 lines
2.3 KiB
Markdown
# 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
|
|
```csharp
|
|
private void OnTimerCallback(object? state)
|
|
{
|
|
if (_disposed) return; // ← Added
|
|
// ...
|
|
}
|
|
```
|
|
|
|
### 2. Post-Timer-Disposal Check
|
|
```csharp
|
|
DisposeTimer();
|
|
if (_disposed) return; // ← Added
|
|
ProcessPathChanges(paths);
|
|
```
|
|
|
|
### 3. Exception Handling
|
|
```csharp
|
|
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
|
|
|
|
- **Full Guide:** [LIBRARYMONITOR_DISPOSAL_FIX.md](./LIBRARYMONITOR_DISPOSAL_FIX.md)
|
|
- **README Updated:** Added to "Error Fixes & Troubleshooting" section
|
|
|
|
## Related Issues
|
|
|
|
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
|