Skip to content

Commit e3404ae

Browse files
Prevent race condition in LoggingService (#11284)
1 parent a1c2e74 commit e3404ae

File tree

1 file changed

+39
-22
lines changed

1 file changed

+39
-22
lines changed

src/Build/BackEnd/Components/Logging/LoggingService.cs

Lines changed: 39 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
using System.Threading;
1111
using Microsoft.Build.BackEnd.Components.RequestBuilder;
1212
using Microsoft.Build.Evaluation;
13+
using Microsoft.Build.Experimental.BuildCheck;
1314
using Microsoft.Build.Experimental.BuildCheck.Infrastructure;
1415
using Microsoft.Build.Framework;
1516
using Microsoft.Build.Shared;
1617
using InternalLoggerException = Microsoft.Build.Exceptions.InternalLoggerException;
1718
using LoggerDescription = Microsoft.Build.Logging.LoggerDescription;
18-
using Microsoft.Build.Experimental.BuildCheck;
1919

2020
#nullable disable
2121

@@ -62,7 +62,7 @@ internal enum LoggingServiceState
6262
ShuttingDown,
6363

6464
/// <summary>
65-
/// The logging service completly shutdown
65+
/// The logging service completely shutdown.
6666
/// </summary>
6767
Shutdown
6868
}
@@ -253,12 +253,14 @@ internal partial class LoggingService : ILoggingService, INodePacketHandler
253253
/// Event set when message is consumed from queue.
254254
/// </summary>
255255
private AutoResetEvent _dequeueEvent;
256+
256257
/// <summary>
257-
/// Event set when queue become empty.
258+
/// Event set when queue become empty.
258259
/// </summary>
259260
private ManualResetEvent _emptyQueueEvent;
261+
260262
/// <summary>
261-
/// Even set when message is added into queue.
263+
/// Event set when message is added into queue.
262264
/// </summary>
263265
private AutoResetEvent _enqueueEvent;
264266

@@ -1408,34 +1410,47 @@ private void StartLoggingEventProcessing()
14081410
void LoggingEventProc()
14091411
{
14101412
var completeAdding = _loggingEventProcessingCancellation.Token;
1411-
WaitHandle[] waitHandlesForNextEvent = { completeAdding.WaitHandle, _enqueueEvent };
1413+
WaitHandle[] waitHandlesForNextEvent = [completeAdding.WaitHandle, _enqueueEvent];
14121414

1413-
do
1415+
try
14141416
{
1415-
if (_eventQueue.TryDequeue(out object ev))
1416-
{
1417-
LoggingEventProcessor(ev);
1418-
_dequeueEvent.Set();
1419-
}
1420-
else
1421-
{
1422-
_emptyQueueEvent.Set();
1417+
// Store field references locally to prevent race with cleanup
1418+
var eventQueue = _eventQueue;
1419+
var dequeueEvent = _dequeueEvent;
1420+
var emptyQueueEvent = _emptyQueueEvent;
1421+
var enqueueEvent = _enqueueEvent;
14231422

1424-
// Wait for next event, or finish.
1425-
if (!completeAdding.IsCancellationRequested && _eventQueue.IsEmpty)
1423+
do
1424+
{
1425+
if (eventQueue.TryDequeue(out object ev))
14261426
{
1427-
WaitHandle.WaitAny(waitHandlesForNextEvent);
1427+
LoggingEventProcessor(ev);
1428+
dequeueEvent?.Set();
14281429
}
1430+
else
1431+
{
1432+
emptyQueueEvent?.Set();
14291433

1430-
_emptyQueueEvent.Reset();
1431-
}
1432-
} while (!_eventQueue.IsEmpty || !completeAdding.IsCancellationRequested);
1434+
// Wait for next event, or finish.
1435+
if (!completeAdding.IsCancellationRequested && eventQueue.IsEmpty)
1436+
{
1437+
WaitHandle.WaitAny(waitHandlesForNextEvent);
1438+
}
14331439

1434-
_emptyQueueEvent.Set();
1440+
emptyQueueEvent.Reset();
1441+
}
1442+
} while (!eventQueue.IsEmpty || !completeAdding.IsCancellationRequested);
1443+
1444+
emptyQueueEvent.Set();
1445+
}
1446+
catch (ObjectDisposedException)
1447+
{
1448+
// Events/queue were disposed during shutdown, exit processing
1449+
return;
1450+
}
14351451
}
14361452
}
14371453

1438-
14391454
/// <summary>
14401455
/// Clean resources used for logging event processing queue.
14411456
/// </summary>
@@ -1448,9 +1463,11 @@ private void CleanLoggingEventProcessing()
14481463
_loggingEventProcessingCancellation?.Dispose();
14491464

14501465
_eventQueue = null;
1466+
14511467
_dequeueEvent = null;
14521468
_enqueueEvent = null;
14531469
_emptyQueueEvent = null;
1470+
14541471
_loggingEventProcessingCancellation = null;
14551472
_loggingEventProcessingThread = null;
14561473
}

0 commit comments

Comments
 (0)