') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); Fix ProcessThreadTests.TestStartTimeProperty flakiness due to /proc visibility race by Copilot · Pull Request #125811 · dotnet/runtime · GitHub
Skip to content

Fix ProcessThreadTests.TestStartTimeProperty flakiness due to /proc visibility race - #125811

Merged
danmoseley merged 4 commits into
mainfrom
copilot/fix-process-thread-tests
Mar 20, 2026
Merged

Fix ProcessThreadTests.TestStartTimeProperty flakiness due to /proc visibility race#125811
danmoseley merged 4 commits into
mainfrom
copilot/fix-process-thread-tests

Conversation

CopilotAI commented Mar 20, 2026

Copy link
Copy Markdown
Contributor

TestStartTimeProperty was flaky (especially on Mono/Linux) because after a new LongRunning thread starts, its /proc/self/task/ entry may not be visible immediately. The previous code called p.Refresh() once then used Assert.Single, failing hard if the entry wasn't ready yet.

Description

Replace the single-shot refresh + Assert.Single with a bounded retry loop that re-calls p.Refresh() until the thread appears (up to 10 attempts, 100ms apart):

intnewThreadId=GetCurrentThreadId();ProcessThreadnewThread=null;for(inti=0;i<10&&newThreadisnull;i++){if(i>0)Thread.Sleep(100);p.Refresh();newThread=p.Threads.Cast<ProcessThread>().FirstOrDefault(t =>t.Id==newThreadId);}Assert.True(newThreadis not null,$"Thread with id {newThreadId} was not found after retrying.");Assert.InRange(newThread.StartTime.ToUniversalTime(),curTime-allowedWindow,DateTime.Now.ToUniversalTime()+allowedWindow);
Original prompt

This section details on the original issue you should resolve

<issue_title>ProcessThreadTests.TestStartTimeProperty failure in CI</issue_title>
<issue_description>```
System.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty [FAIL]
Assert.Single() Failure: The collection did not contain any matching items
Expected: (predicate expression)
Collection: [System.Diagnostics.ProcessThread, System.Diagnostics.ProcessThread, System.Diagnostics.ProcessThread, System.Diagnostics.ProcessThread, System.Diagnostics.ProcessThread, ···]
Stack Trace:
//src/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs(156,0): at System.Diagnostics.Tests.ProcessThreadTests.<>c__DisplayClass4_2.b__0()
/
/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs(2396,0): at System.Threading.Tasks.Task.InnerInvoke()
//src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs(2384,0): at System.Threading.Tasks.Task.<>c.<.cctor>b__292_0(Object obj)
/
/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs(179,0): at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
--- End of stack trace from previous location ---
//src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs(203,0): at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
/
/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs(2342,0): at System.Threading.Tasks.Task.ExecuteWithThreadLocal(Task& currentTaskSlot, Thread threadPoolThread)
--- End of stack trace from previous location ---
/_/src/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs(149,0): at System.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty()
--- End of stack trace from previous location ---


## Build Information
Build: https://dev.azure.com/dnceng-public/cbb18261-c48f-4abb-8651-8cdcb5474649/_build/results?buildId=755830
Build error leg or test failing: System.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty
Pull request: https://github.com/dotnet/runtime/pull/105519
<!-- Error message template -->
## Error Message
Fill the error message using [step by step known issues guidance](https://github.com/dotnet/arcade/blob/main/Documentation/Projects/Build%20Analysis/KnownIssueJsonStepByStep.md).
<!-- Use ErrorMessage for String.Contains matches. Use ErrorPattern for regex matches (single line/no backtracking). Set BuildRetry to `true` to retry builds with this error. Set ExcludeConsoleLog to `true` to skip helix logs analysis. -->
```json
{
"ErrorMessage": ["System.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty [FAIL]","The collection did not contain any matching items"],
"ErrorPattern": "",
"BuildRetry": false,
"ExcludeConsoleLog": false
}

Known issue validation

Build: 🔎https://dev.azure.com/dnceng-public/public/_build/results?buildId=755830
Error message validated:[System.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty [FAIL] The collection did not contain any matching items]
Result validation: ✅ Known issue matched with the provided build.
Validation performed at: 7/26/2024 12:06:54 AM UTC

Report

BuildDefinitionTestPull Request
1342756dotnet/runtimeSystem.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty#115996
1332497dotnet/runtimeSystem.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty#125022
1326378dotnet/runtimeSystem.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty#124923
1315488dotnet/runtime[System.Diagnostics.Tests.ProcessThreadTests.TestStartTimeProperty](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1315488&view=ms.vss-test-web.build...

📱 Kick off Copilot coding agent tasks wherever you are with GitHub Mobile, available on iOS and Android.

CopilotAIand others added 2 commits March 20, 2026 00:31
…y loop
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com>
CopilotAI changed the title [WIP] Fix ProcessThreadTests.TestStartTimeProperty failure in CIFix ProcessThreadTests.TestStartTimeProperty flakiness due to /proc visibility raceMar 20, 2026
CopilotAI requested a review from danmoseleyMarch 20, 2026 00:34
@danmoseley
danmoseley requested a review from CopilotMarch 20, 2026 01:09
@danmoseley
danmoseley marked this pull request as ready for review March 20, 2026 01:10

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR reduces flakiness in ProcessThreadTests.TestStartTimeProperty by handling a race where a newly started thread may not immediately appear in Process.Threads (notably on Linux/Mono), replacing a single-shot refresh + Assert.Single with a bounded retry loop.

Changes:

  • Remove the single p.Refresh() + Assert.Single(...) lookup for the spawned thread.
  • Add a bounded retry loop that refreshes and searches for the thread by ID before asserting.
  • Improve failure behavior by emitting a clearer assertion message when the thread never becomes visible.

Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs Outdated
Comment threadsrc/libraries/System.Diagnostics.Process/tests/ProcessThreadTests.cs Outdated
- Reword /proc-specific comment to be platform-agnostic
- Use DateTime.UtcNow instead of DateTime.Now.ToUniversalTime()
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@adamsitnikadamsitnik left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@danmoseley
danmoseley merged commit 4e54117 into mainMar 20, 2026
78 of 84 checks passed
@danmoseley
danmoseley deleted the copilot/fix-process-thread-tests branch March 20, 2026 14:16
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ProcessThreadTests.TestStartTimeProperty failure in CI

5 participants

@adamsitnik@danmoseley@jkotas