From bd423835a6fcf9502c7bef372036edb55031590d Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 4 Oct 2023 11:50:53 +0900 Subject: [PATCH 1/3] Fix race condition in ThreadedTaskScheduler when adding tasks --- osu.Framework/Threading/ThreadedTaskScheduler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Framework/Threading/ThreadedTaskScheduler.cs b/osu.Framework/Threading/ThreadedTaskScheduler.cs index 5b40d62061..4c86068ac2 100644 --- a/osu.Framework/Threading/ThreadedTaskScheduler.cs +++ b/osu.Framework/Threading/ThreadedTaskScheduler.cs @@ -87,7 +87,7 @@ protected override void QueueTask(Task task) { tasks.Add(task); } - catch (ObjectDisposedException) + catch (Exception ex) when (ex is InvalidOperationException or ObjectDisposedException) { // tasks may have been disposed. there's no easy way to check on this other than catch for it. Logger.Log($"Task was queued for execution on a {nameof(ThreadedTaskScheduler)} ({name}) after it was disposed. The task will be executed inline."); From 318025ebfa20e44638931640869bfb6b401f836c Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Wed, 4 Oct 2023 14:13:48 +0900 Subject: [PATCH 2/3] Add stress test --- .../Threading/ThreadedTaskSchedulerTest.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs b/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs index 02f76fca36..acf0620439 100644 --- a/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs +++ b/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs @@ -83,5 +83,28 @@ public void EnsureScheduledTaskReturnsOnDisposal() Assert.That(run.Wait(30000)); Assert.That(exited.Wait(30000)); } + + [Test] + [Repeat(1000)] + public void QueueAndDisposeStressTest() + { + ThreadedTaskScheduler scheduler = new ThreadedTaskScheduler(1, string.Empty); + + Thread disposeThread = new Thread(() => + { + scheduler.Dispose(); + }) { IsBackground = true }; + + Thread queueThread = new Thread(() => + { + Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler); + }) { IsBackground = true }; + + disposeThread.Start(); + queueThread.Start(); + + disposeThread.Join(); + queueThread.Join(); + } } } From 4257d72e2c73b4f9f2f11aa0946ad7560bb81f0d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 4 Oct 2023 14:36:07 +0900 Subject: [PATCH 3/3] Fix(?) formatting --- .../Threading/ThreadedTaskSchedulerTest.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs b/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs index acf0620439..a76840e84a 100644 --- a/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs +++ b/osu.Framework.Tests/Threading/ThreadedTaskSchedulerTest.cs @@ -93,12 +93,18 @@ public void QueueAndDisposeStressTest() Thread disposeThread = new Thread(() => { scheduler.Dispose(); - }) { IsBackground = true }; + }) + { + IsBackground = true + }; Thread queueThread = new Thread(() => { Task.Factory.StartNew(() => { }, CancellationToken.None, TaskCreationOptions.HideScheduler, scheduler); - }) { IsBackground = true }; + }) + { + IsBackground = true + }; disposeThread.Start(); queueThread.Start();