Skip to content

Fix: release file handles on DocumentDbContext constructor failure#130

Merged
mrdevrobot merged 6 commits into
mainfrom
copilot/fix-database-file-lock-issue
Jul 22, 2026
Merged

Fix: release file handles on DocumentDbContext constructor failure#130
mrdevrobot merged 6 commits into
mainfrom
copilot/fix-database-file-lock-issue

Conversation

Copilot AI commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

When DocumentDbContext throws during construction (e.g. wrong encryption password → AuthenticationTagMismatchException inside InitializeCollections()), the StorageEngine/PageFile and memory-mapped handles were never disposed, leaving the database file locked for the lifetime of the process.

Changes

src/BLite.Core/DocumentDbContext.cs

  • Wrapped the model-build + InitializeCollections() + DropOrphanCollections() + GDPR-validation sequence in a try/catch in all three "real" constructors
  • On exception: _storage.Dispose(), _cdc.Dispose(), _ownedCoordinator?.Dispose() (zeros key material), _disposed = true, then rethrow
  • The StorageEngine storage overload skips disposing _storage on failure — it is caller-owned
_storage = new StorageEngine(databasePath, config);
// ...
try
{
    _model = modelBuilder.GetEntityBuilders();
    InitializeCollections();   // ← throws here with wrong password
    DropOrphanCollections();
    RunGdprStrictValidation(kvOptions);
}
catch
{
    _storage.Dispose();        // releases PageFile / memory-mapped handles
    _cdc.Dispose();
    _ownedCoordinator?.Dispose();
    _disposed = true;
    throw;
}

tests/BLite.Tests/EncryptionTests.cs

  • Added regression test DocumentDbContext_ConstructorFailure_WrongPassword_FileNotLocked: creates an encrypted DB, checkpoints it, then opens it with the wrong password → asserts the constructor throws → asserts File.Delete succeeds in the same process without GC intervention

Copilot AI changed the title [WIP] Fix database file locking after DocumentDbContext failure Fix: release file handles on DocumentDbContext constructor failure Jul 21, 2026
Copilot AI requested a review from mrdevrobot July 21, 2026 20:21
@mrdevrobot
mrdevrobot marked this pull request as ready for review July 21, 2026 20:27
Copilot AI review requested due to automatic review settings July 21, 2026 20:27
@mrdevrobot mrdevrobot added bug Something isn't working core labels Jul 21, 2026
@mrdevrobot mrdevrobot added this to BLite Jul 21, 2026
@github-project-automation github-project-automation Bot moved this to Todo in BLite Jul 21, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses a resource-leak bug where DocumentDbContext constructor failures (notably during encrypted store open) could leave the underlying database file locked due to undisposed storage/file handles, preventing in-process delete/replace flows.

Changes:

  • Added exception handling in DocumentDbContext constructors to dispose acquired resources when initialization fails.
  • Added a regression test ensuring a failed open with the wrong encryption password does not leave the DB file locked.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/BLite.Core/DocumentDbContext.cs Wraps model/collection initialization in try/catch and disposes storage/CDC (and owned encryption coordinator where applicable) on constructor failure.
tests/BLite.Tests/EncryptionTests.cs Adds a regression test for issue #129 asserting the database file can be deleted after a constructor failure caused by wrong encryption credentials.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/BLite.Core/DocumentDbContext.cs
Comment thread src/BLite.Core/DocumentDbContext.cs
Comment on lines +224 to +228
try
{
var modelBuilder = new ModelBuilder();
OnModelCreating(modelBuilder);
_model = modelBuilder.GetEntityBuilders();
Comment thread tests/BLite.Tests/EncryptionTests.cs Outdated
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
@mrdevrobot

Copy link
Copy Markdown
Contributor

@copilot

[xUnit.net 00:00:30.30] BLite.Tests.ConcurrencyPressureTests.FindConcurrencyBreakingPoint_ServerLayout [SKIP]
Skipped BLite.Tests.ConcurrencyPressureTests.ReadModifyWrite_DefaultLayout [1 ms]
Skipped BLite.Tests.ConcurrencyPressureTests.FindConcurrencyBreakingPoint_ServerLayout [1 ms]
[xUnit.net 00:00:41.66] BLite.Tests.EncryptionTests.DocumentDbContext_ConstructorFailure_WrongPassword_FileNotLocked [FAIL]
Failed BLite.Tests.EncryptionTests.DocumentDbContext_ConstructorFailure_WrongPassword_FileNotLocked [18 ms]
Error Message:
System.IO.IOException : The process cannot access the file '/tmp/enc_test_e5851d3a-b340-414e-a113-239f9731077f.db' because it is being used by another process.
Stack Trace:
at Microsoft.Win32.SafeHandles.SafeFileHandle.Init(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Int64& fileLength, UnixFileMode& filePermissions)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, UnixFileMode openPermissions, Int64& fileLength, UnixFileMode& filePermissions, Boolean failForSymlink, Boolean& wasSymlink, Func4 createOpenException) at System.IO.Strategies.OSFileStreamStrategy..ctor(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable1 unixCreateMode)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
at BLite.Tests.EncryptionTests.DocumentDbContext_ConstructorFailure_WrongPassword_FileNotLocked() in /home/runner/work/BLite/BLite/tests/BLite.Tests/EncryptionTests.cs:line 1615
--- End of stack trace from previous location ---

Copilot AI commented Jul 21, 2026

Copy link
Copy Markdown
Contributor Author

@copilot

[xUnit.net 00:00:30.30] BLite.Tests.ConcurrencyPressureTests.FindConcurrencyBreakingPoint_ServerLayout [SKIP]
...

Fixed in 5719af4. The lock was coming from StorageEngine failing during open before DocumentDbContext could finish cleanup; constructor-failure cleanup now disposes partially opened storage, and the targeted encryption tests pass.

@mrdevrobot
mrdevrobot merged commit b5c709e into main Jul 22, 2026
6 checks passed
@github-project-automation github-project-automation Bot moved this from Todo to QA in BLite Jul 22, 2026
@mrdevrobot
mrdevrobot deleted the copilot/fix-database-file-lock-issue branch July 22, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working core

Projects

Status: QA

Development

Successfully merging this pull request may close these issues.

Database file remains locked after DocumentDbContext constructor failure

3 participants