mbdavid / LiteDB

LiteDB - A .NET NoSQL Document Store in a single data file
http://www.litedb.org
MIT License
8.36k stars 1.22k forks source link

[BUG] DiskWriterQueue captures synchronization context #2446

Open alexbereznikov opened 3 months ago

alexbereznikov commented 3 months ago

Version LiteDB v5.0.19, Windows 11, .NET 6

Describe the bug DiskWriterQueue captures synchronization context/task scheduler due to omitting task scheduler parameter in Task.Factory.StartNew. This can cause hard to debug side effects when custom synchronization contexts are being used. For contexts that can become invalid, Post call caused by state machine inside DiskWriterQueue.ExecuteQueue can break application.

Code to Reproduce Unfortunately, I can't reproduce this issue in a new project.

Expected behavior DiskWriterQueue should not capture synchronization context for its own operations.

Screenshots/Stacktrace Part of the stack trace that leads to this error:

   at Zero.Foundation.Threading.TaskQueueSynchronizationContext.Post(SendOrPostCallback d, Object state) in C:\s\apollo.desktop\src\Zero.Foundation\Threading\TaskQueueSynchronizationContext.cs:line 40
   at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_1(Object state)
   at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
   at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callback, TState& state)
   at System.Threading.QueueUserWorkItemCallback.Execute()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
   at System.Threading.Thread.StartCallback()

Logs from custom synchronization context that shows what is being called:

POST <.cctor>b__8_0 System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation+<>c
MoveNext System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Threading.Tasks.VoidTaskResult,LiteDB.Engine.DiskWriterQueue+<ExecuteQueue>d__14] System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1+AsyncStateMachineBox`1[System.Threading.Tasks.VoidTaskResult,LiteDB.Engine.DiskWriterQueue+<ExecuteQueue>d__14]

Additional context In our case, integration tests started to fail after upgrading from v5.0.17 to v5.0.19. We're using a custom synchronization context to combine async code and transactions that are per-thread.

Introduced in f21cd8405eda7c7b59b018c9a541b0c3605eb5da

alexbereznikov commented 3 days ago

Should be fixed in scope of #2515