Skip to content

Commit a0b9c8f

Browse files
thomhurstclaude
andcommitted
fix: ensure thread-safe initialization of console line buffers
Addresses post-merge feedback from PR #4549 regarding thread-safety concerns in console buffer lazy initialization. Replaced nullable StringBuilder fields with Lazy<StringBuilder> to guarantee thread-safe initialization when multiple threads access GetConsoleStdOutLineBuffer() or GetConsoleStdErrLineBuffer() concurrently. The previous implementation using ??= was not thread-safe and could result in multiple StringBuilder instances being created before assignment completes, undermining per-context buffer isolation. Benefits: - Thread-safe by default with Lazy<T> - No manual double-checked locking needed - Cleaner, more idiomatic C# code - AOT-compatible Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
1 parent c01a6fc commit a0b9c8f

File tree

1 file changed

+5
-4
lines changed

1 file changed

+5
-4
lines changed

TUnit.Core/Context.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ TestContext.Current as Context
2929

3030
// Console interceptor line buffers for partial writes (Console.Write without newline)
3131
// These are stored per-context to prevent output mixing between parallel tests
32-
private StringBuilder? _consoleStdOutLineBuffer;
33-
private StringBuilder? _consoleStdErrLineBuffer;
32+
// Using Lazy<T> for thread-safe initialization
33+
private readonly Lazy<StringBuilder> _consoleStdOutLineBuffer = new(() => new StringBuilder());
34+
private readonly Lazy<StringBuilder> _consoleStdErrLineBuffer = new(() => new StringBuilder());
3435
private readonly object _consoleStdOutBufferLock = new();
3536
private readonly object _consoleStdErrBufferLock = new();
3637

@@ -43,12 +44,12 @@ TestContext.Current as Context
4344
// Internal accessors for console interceptor line buffers with thread safety
4445
internal (StringBuilder Buffer, object Lock) GetConsoleStdOutLineBuffer()
4546
{
46-
return (_consoleStdOutLineBuffer ??= new StringBuilder(), _consoleStdOutBufferLock);
47+
return (_consoleStdOutLineBuffer.Value, _consoleStdOutBufferLock);
4748
}
4849

4950
internal (StringBuilder Buffer, object Lock) GetConsoleStdErrLineBuffer()
5051
{
51-
return (_consoleStdErrLineBuffer ??= new StringBuilder(), _consoleStdErrBufferLock);
52+
return (_consoleStdErrLineBuffer.Value, _consoleStdErrBufferLock);
5253
}
5354

5455
internal Context(Context? parent)

0 commit comments

Comments
 (0)