Skip to content

Commit fb61718

Browse files
authored
Fix a thread pool test (#67399)
- The test verifies that cooperative blocking in `Task.Wait()` causes threads to be injected quickly enough that it does not time out due to starvation - Cooperative blocking checks memory usage and limit, and beyond a threshold of memory usage does not inject threads quickly - Following a build of the runtime repo, there are several `dotnet` processes that remain running, each using several 100s of MBs and one using ~1.3 GB of memory - If the test runs soon after the build, before those processes exit, it's possible for the reported memory usage to be high enough that the test would fail - Added a config var to ignore memory usage and used it in the test Fixes #66852
1 parent 6b473fb commit fb61718

File tree

3 files changed

+14
-10
lines changed

3 files changed

+14
-10
lines changed

src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.Blocking.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ private uint PerformBlockingAdjustment(bool previousDelayElapsed, out bool addWo
180180

181181
do
182182
{
183-
if (newNumThreadsGoal <= counts.NumExistingThreads)
183+
if (newNumThreadsGoal <= counts.NumExistingThreads || BlockingConfig.IgnoreMemoryUsage)
184184
{
185185
break;
186186
}
@@ -260,6 +260,8 @@ private static class BlockingConfig
260260
{
261261
public static readonly bool IsCooperativeBlockingEnabled =
262262
AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.Blocking.CooperativeBlocking", true);
263+
public static readonly bool IgnoreMemoryUsage =
264+
AppContextConfigHelper.GetBooleanConfig("System.Threading.ThreadPool.Blocking.IgnoreMemoryUsage", false);
263265

264266
public static readonly short ThreadsToAddWithoutDelay;
265267
public static readonly short ThreadsPerDelayStep;

src/libraries/System.Private.CoreLib/src/System/Threading/PortableThreadPool.GateThread.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ private static void GateThreadStart()
3636
LowLevelLock threadAdjustmentLock = threadPoolInstance._threadAdjustmentLock;
3737
DelayHelper delayHelper = default;
3838

39-
if (BlockingConfig.IsCooperativeBlockingEnabled)
39+
if (BlockingConfig.IsCooperativeBlockingEnabled && !BlockingConfig.IgnoreMemoryUsage)
4040
{
4141
// Initialize memory usage and limits, and register to update them on gen 2 GCs
4242
threadPoolInstance.OnGen2GCCallback();

src/libraries/System.Threading.ThreadPool/tests/ThreadPoolTests.cs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,6 @@ public static void ThreadPoolThreadCreationDoesNotTransferExecutionContext()
907907
}
908908

909909
[ConditionalFact(nameof(IsThreadingAndRemoteExecutorSupported))]
910-
[ActiveIssue("https://github.com/dotnet/runtime/issues/66852", TestPlatforms.OSX)]
911910
public static void CooperativeBlockingCanCreateThreadsFaster()
912911
{
913912
// Run in a separate process to test in a clean thread pool environment such that work items queued by the test
@@ -925,6 +924,7 @@ public static void CooperativeBlockingCanCreateThreadsFaster()
925924
int workItemCount = processorCount + 120;
926925
SetBlockingConfigValue("ThreadsToAddWithoutDelay_ProcCountFactor", 1);
927926
SetBlockingConfigValue("MaxDelayMs", 1);
927+
SetBlockingConfigValue("IgnoreMemoryUsage", true);
928928

929929
var allWorkItemsUnblocked = new AutoResetEvent(false);
930930

@@ -955,17 +955,19 @@ public static void CooperativeBlockingCanCreateThreadsFaster()
955955
Assert.True(allWorkItemsUnblocked.WaitOne(30_000));
956956
}
957957

958-
void SetBlockingConfigValue(string name, int value) =>
958+
void SetBlockingConfigValue(string name, object value) =>
959959
AppContextSetData("System.Threading.ThreadPool.Blocking." + name, value);
960960

961961
void AppContextSetData(string name, object value)
962962
{
963-
typeof(AppContext).InvokeMember(
964-
"SetData",
965-
BindingFlags.ExactBinding | BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
966-
null,
967-
null,
968-
new object[] { name, value });
963+
if (value is bool boolValue)
964+
{
965+
AppContext.SetSwitch(name, boolValue);
966+
}
967+
else
968+
{
969+
AppContext.SetData(name, value);
970+
}
969971
}
970972
}).Dispose();
971973
}

0 commit comments

Comments
 (0)