56 lines
1.5 KiB
C#
56 lines
1.5 KiB
C#
using System;
|
|
using System.Threading;
|
|
using Xunit;
|
|
|
|
namespace Server.Tests;
|
|
|
|
[Collection("Sequential Server Tests")]
|
|
public class SerializationThreadWorkerHandshakeTests
|
|
{
|
|
// The pause handshake must tolerate a new cycle starting the moment _stopEvent is
|
|
// set (Exit right after Sleep). The watchdog turns a reintroduced deadlock into a
|
|
// failure instead of a hung run.
|
|
[Fact]
|
|
public void WakeSleepExitChurn_NeverDeadlocks()
|
|
{
|
|
Exception failure = null;
|
|
var done = new ManualResetEventSlim();
|
|
|
|
var churn = new Thread(() =>
|
|
{
|
|
try
|
|
{
|
|
for (var i = 0; i < 2000; i++)
|
|
{
|
|
var source = new SerializationChunkSource();
|
|
var worker = new SerializationThreadWorker(0, source);
|
|
worker.AllocateHeap();
|
|
|
|
worker.Wake();
|
|
worker.Sleep();
|
|
worker.Exit(); // Immediately after Sleep returns — the racy window.
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
failure = e;
|
|
}
|
|
finally
|
|
{
|
|
done.Set();
|
|
}
|
|
})
|
|
{
|
|
IsBackground = true,
|
|
Name = "Handshake Churn"
|
|
};
|
|
|
|
churn.Start();
|
|
|
|
Assert.True(
|
|
done.Wait(TimeSpan.FromMinutes(2)),
|
|
"Worker pause/exit handshake deadlocked (owner blocked in Sleep or worker spinning)."
|
|
);
|
|
Assert.Null(failure);
|
|
}
|
|
}
|