Skip to content
New issue

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

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

Already on GitHub? # to your account

[BUG] LiteDB Shared connection when accessed by multiple threads can cause errors #2292

Open
dev-joshi opened this issue Mar 6, 2023 · 0 comments
Labels

Comments

@dev-joshi
Copy link

dev-joshi commented Mar 6, 2023

Version
Which LiteDB version/OS/.NET framework version are you using.
LiteDB 5.0.15
.Net Framework 4.6.2

Describe the bug
When a single LiteDB object is created with connection type Shared and then it's used by multiple threads concurrently, then it can cause errors.

Code to Reproduce

The following code starts 100 threads in a batch to randomly read or write to a single LiteDB shared connection and keeps repeating the batch until a thread encounters an error :

`
namespace YetAnotherConsoleApp
{
using LiteDB;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

public class Program
{
    private static string LiteDBFileName = @"Artifacts\TestDatabase.litedb";
    private static string LiteDbPassword = "P@ssw0rd";
    private static int exceptionCount = 0;
    private static int iterations = 0;

    public static void Main(string[] args)
    {
        while (exceptionCount == 0)
        {
            Console.WriteLine($"Starting Iteration {++iterations}");
            CleanupDirectory();

            var liteDatabase = new LiteDatabase($"FileName={LiteDBFileName};Password='{LiteDbPassword}';Connection='Shared'");

            var threadList = new List<Thread>();
            for (int i = 0; i < 100; i++)
            {
                var t = new Thread(() => ReadOrWriteIntoDB(liteDatabase));
                t.Start();
                threadList.Add(t);
            }
            
            foreach (var thread in threadList)
                thread.Join();

            liteDatabase.Dispose();
            liteDatabase = null;
        }
    }

    private static void CleanupDirectory()
    {
        var workingDir = Path.GetDirectoryName(LiteDBFileName);
        if (Directory.Exists(workingDir))
            Directory.Delete(workingDir, true);
        Directory.CreateDirectory(workingDir);
    }

    private static void ReadOrWriteIntoDB(ILiteDatabase liteDatabase)
    {
        var collection = liteDatabase.GetCollection<TestEntity>(nameof(TestEntity));

        var r = new Random();
        var b = new byte[10000];
        for (int i = 0; i < b.Length; i++)
            b[i] = (byte)r.Next();

        var read = r.Next(1, 10) % 2 == 0;
        //Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} {(read ? "reading" : "writing")} to DB");

        if (read)
        {
            try
            {
                var all = collection.FindAll().ToList();
            }
            catch (Exception e)
            {
                Interlocked.Increment(ref exceptionCount);
                Console.WriteLine($"Failed to read DB from Thread {Thread.CurrentThread.ManagedThreadId} : {e}");
            }
        }
        else
        {
            try
            {
                _ = collection.Upsert(new TestEntity
                {
                    Name = $"Inserted from Thread {Thread.CurrentThread.ManagedThreadId}",
                    Data = b,
                });
            }
            catch (Exception e)
            {
                Interlocked.Increment(ref exceptionCount);
                Console.WriteLine($"Failed to write to DB from Thread {Thread.CurrentThread.ManagedThreadId} : {e}");
            }
        }
        
        //Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} exiting");
    }
}

internal class TestEntity
{
    public string Name { get; set; }
    public byte[] Data { get; set; }
}

}
`

Expected behavior
Expectation is the above program keeps running without any errors.

Screenshots/Stacktrace
image
image

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

No branches or pull requests

1 participant