[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 - #130986

Closed
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue
Closed

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86#130986
VSadov with Copilot wants to merge 1 commit into
mainfrom
copilot/release100-fix-assert-issue

Conversation

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

main PR #127638

Description

On x86 Windows lacking RtlRestoreContext, Thread::RestoreContextSimulated called HandleThreadAbort() while m_RedirectContextInUse was still true. Constructing the ThreadAbortException runs managed code, during which a concurrent GC redirect fires MarkRedirectContextInUse() and hits the !m_RedirectContextInUse assert (and can corrupt the saved context).

Backport of #127638 to release/10.0 (src/coreclr/vm/threadsuspend.cpp, +10/-12):

  • Removed the inlined HandleThreadAbort() from RestoreContextSimulated.
  • Moved the #ifdef TARGET_X86RestoreContextSimulated call in RedirectedHandledJITCase to after the existing COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share a single abort-check path.

Byte-for-byte identical to the merged main fix except for preserving release/10.0's __UNREACHABLE() spelling.

Customer Impact

Any x86 .NET 10 process where ntdll lacks RtlRestoreContext (x86 Win7, WOW64 on Win7, and similar) can hit a double-redirect race that corrupts the saved thread context, causing random, hard-to-diagnose crashes. .NET 10 is LTS (supported through Nov 2028).

Regression

No. Pre-existing bug in the x86 RestoreContextSimulated path, not introduced in a recent release.

Testing

Manual review confirming the diff matches the merged main change. The affected code is entirely under #ifdef TARGET_X86, so it is not exercised by non-Windows-x86 build/test configurations.

Risk

Low. Minimal, localized reordering of an existing abort check; already reviewed and shipping on main since 2026-05-01.

Package authoring no longer needed in .NET 9

IMPORTANT: Starting with .NET 9, you no longer need to edit a NuGet package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older versions.

CopilotAI review requested due to automatic review settings July 17, 2026 18: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.

Copilot was unable to review this pull request because there is no eligible user to bill. To allow Copilot reviews on bot-authored pull requests, enable direct organization billing in your organization's Copilot settings.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

CopilotAI commented Jul 17, 2026

Copy link
Copy Markdown
ContributorAuthor
Azure Pipelines:
15 pipeline(s) were filtered out due to trigger conditions.

...

⚠️ This PR's base branch needs to be changed to release/10.0

I've prepared the backport of #127638, but I cannot push it because this PR currently targets main as its base branch (base = main @ 0f08396), whereas this is a request to backport the fix to release/10.0.

Two consequences of the wrong base:

  1. main already contains the fix. PR Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86 #127638 was merged to main on 2026-05-01 (bd9e85e4). There is no diff to apply against main, so a backport cannot be represented while the base stays main.
  2. The automation rebases the working branch onto the (main-based) PR head, which replays the entire release/10.0 history and conflicts, so the release/10.0-based backport commit can't be pushed.

What needs to happen

Please change the base branch of this PR from main to release/10.0 (Edit → base dropdown). Once retargeted, the backport commit can be pushed cleanly.

The prepared change (identical to #127638, minimal +10/-12 in src/coreclr/vm/threadsuspend.cpp)

  • Remove the inlined pThread->HandleThreadAbort(); from Thread::RestoreContextSimulated.
  • Move the #ifdef TARGET_X86RestoreContextSimulated(...) call in RedirectedHandledJITCase to after the COMPlusCheckForAbort() block, so the x86 SEH path and the RtlRestoreContext path share one abort-check path.
 void Thread::RestoreContextSimulated(Thread* pThread, CONTEXT* pCtx, void* pFrame, DWORD dwLastError)
{
- pThread->HandleThreadAbort(); // Might throw an exception.-
// A counter to avoid a nasty case where an
// up-stack filter throws another exception
// causing our filter to be run again for
@@ RedirectedHandledJITCase @@
// Once we get here the suspension is over!
// We will restore the state as it was at the point of redirection
// and continue normal execution.
-#ifdef TARGET_X86- if (!g_pfnRtlRestoreContext)- {- RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);-- // we never return to the caller.- __UNREACHABLE();- }-#endif // TARGET_X86-
UINT_PTR uAbortAddr;
UINT_PTR uResumePC = (UINT_PTR)GetIP(pCtx);
@@ @@
SetIP(pCtx, uAbortAddr);
}
+#ifdef TARGET_X86+ if (!g_pfnRtlRestoreContext)+ {+ RestoreContextSimulated(pThread, pCtx, &frame, dwLastError);++ // we never return to the caller.+ __UNREACHABLE();+ }+#endif // TARGET_X86+
// Unlink the frame in preparation for resuming in managed code
frame.Pop();

(The only difference vs the main commit is preserving release/10.0's __UNREACHABLE() spelling.)

Note

This comment was generated by GitHub Copilot.

CopilotAI changed the title [WIP] Backport #127638 to fix assert in RestoreContextSimulated[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86Jul 17, 2026
CopilotAI requested a review from VSadovJuly 17, 2026 18:25
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[release/10.0] Backport #127638: Fix !m_RedirectContextInUse assert in RestoreContextSimulated on win-x86

3 participants

@VSadov