Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] FileStreamFactory.GetStream() neglects to dispose of FileStream when not returned #2579

Open
rtwede opened this issue Jan 9, 2025 · 2 comments
Labels

Comments

@rtwede
Copy link

rtwede commented Jan 9, 2025

Version
5.0.21

Describe the bug
When an exception is thrown by FileStreamFactory.GetStream(...) after creating the FileStream, the stream becomes orphaned/unreachable, but is not disposed properly, holding an open handle to the file with no controlled or deterministic way to dispose of it.
This causes conflicts with other calls/processes which may want to manipulate this file after such an exception occurs.

Code to Reproduce
Write a small snippet to isolate your bug and could be possible to our team test. (REQUIRED)

/* given a pre-existing file.db protected with a password different than the one provided  */
try {
  var engineSettings = new EngineSettings { Filename = "file.db", Password="incorrectPassword", ReadOnly=ReadOnly }
  var engine = new LiteEngine(engineSettings);
} catch {
  File.Delete("file.db");  // Will throw access violation due to file already in use in another process.
}

Expected behavior
Disposable objects should always be disposed before going out of scope to ensure they aren't left dangling indefinitely or non-deterministically (until GC).

Screenshots/Stacktrace

Additional context

@rtwede rtwede added the bug label Jan 9, 2025
@rtwede
Copy link
Author

rtwede commented Jan 9, 2025

Here's the fixed GetStream() method:
`
public Stream GetStream(bool canWrite, bool sequencial)
{
var write = canWrite && (_readonly == false);

var fileMode = _readonly ? System.IO.FileMode.Open : System.IO.FileMode.OpenOrCreate;
var fileAccess = write ? FileAccess.ReadWrite : FileAccess.Read;
var fileShare = write ? FileShare.Read : FileShare.ReadWrite;
var fileOptions = sequencial ? FileOptions.SequentialScan : FileOptions.RandomAccess;

var isNewFile = write && this.Exists() == false;

var stream = new FileStream(_filename,
    fileMode,
    fileAccess,
    fileShare,
    PAGE_SIZE,
    fileOptions);

try
{

    if (isNewFile && _hidden)
    {
        File.SetAttributes(_filename, FileAttributes.Hidden);
    }

    return _password == null || !_useAesStream ? (Stream)stream : new AesStream(_password, stream);
}
catch
{
    stream.Dispose();
    throw;
}

}
`

@JKamsker
Copy link
Collaborator

JKamsker commented Jan 9, 2025

Great! Can you issue a pullrequest for it? Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants