From ebfc39fb494236d5f2eaf9efd3fd2ffa3aa14f7a Mon Sep 17 00:00:00 2001 From: Tom McDonald Date: Fri, 17 Apr 2026 20:44:32 -0400 Subject: [PATCH 1/4] Suppress debugger filter notification for UCO entrypoint during EH dispatch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #126222 moved the app entrypoint from native CallDescrWorkerInternal to managed Environment.CallEntryPoint (UnmanagedCallersOnly). This method has a filter clause (catch when (captureException)) that exists in the EH table even when captureException is false. During first-pass exception dispatch, MakeCallbacksRelatedToHandler notifies the debugger about the filter via ExceptionFilter() before the filter funclet evaluates. The debugger intercepts at this notification, preventing the exception from propagating as unhandled — breaking debugger exception interception scenarios. Skip the debugger ExceptionFilter notification for the known UCO entrypoint method while preserving profiler and ETW notifications. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/coreclr/vm/exinfo.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/coreclr/vm/exinfo.cpp b/src/coreclr/vm/exinfo.cpp index a38cf79104560c..791fa1799dcf4a 100644 --- a/src/coreclr/vm/exinfo.cpp +++ b/src/coreclr/vm/exinfo.cpp @@ -179,7 +179,15 @@ void ExInfo::MakeCallbacksRelatedToHandler( if (fIsFilterHandler) { m_EHClauseInfo.SetEHClauseType(COR_PRF_CLAUSE_FILTER); - EEToDebuggerExceptionInterfaceWrapper::ExceptionFilter(pMD, (TADDR) dwHandlerStartPC, pEHClause->FilterOffset, (BYTE*)sf.SP); + + // Suppress the debugger filter notification for runtime-invoked UCO entrypoint methods. + // These methods have filter clauses (e.g., `catch when (captureException)`) that may + // return false, but the debugger intercepts at the notification before the filter + // evaluates, preventing the exception from propagating as unhandled. + if (pMD != g_pEnvironmentCallEntryPointMethodDesc) + { + EEToDebuggerExceptionInterfaceWrapper::ExceptionFilter(pMD, (TADDR) dwHandlerStartPC, pEHClause->FilterOffset, (BYTE*)sf.SP); + } EEToProfilerExceptionInterfaceWrapper::ExceptionSearchFilterEnter(pMD); ETW::ExceptionLog::ExceptionFilterBegin(pMD, (PVOID)dwHandlerStartPC); From ed52a280c525ffeb578e960c364e50d398d14595 Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 17 Apr 2026 18:01:05 -0700 Subject: [PATCH 2/4] Apply suggestion from @jkotas --- src/coreclr/vm/exinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/exinfo.cpp b/src/coreclr/vm/exinfo.cpp index 791fa1799dcf4a..6f53997a95b1d9 100644 --- a/src/coreclr/vm/exinfo.cpp +++ b/src/coreclr/vm/exinfo.cpp @@ -180,8 +180,8 @@ void ExInfo::MakeCallbacksRelatedToHandler( { m_EHClauseInfo.SetEHClauseType(COR_PRF_CLAUSE_FILTER); - // Suppress the debugger filter notification for runtime-invoked UCO entrypoint methods. - // These methods have filter clauses (e.g., `catch when (captureException)`) that may + // Suppress the debugger filter notification for runtime helper that invokes + // the main program entrypoint. This method has filter clauses that may // return false, but the debugger intercepts at the notification before the filter // evaluates, preventing the exception from propagating as unhandled. if (pMD != g_pEnvironmentCallEntryPointMethodDesc) From e506d84739aaac446e74bcb444d88ed0b8d6844a Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 17 Apr 2026 18:13:22 -0700 Subject: [PATCH 3/4] Apply suggestion from @jkotas --- src/coreclr/vm/exinfo.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/coreclr/vm/exinfo.cpp b/src/coreclr/vm/exinfo.cpp index 6f53997a95b1d9..6733c9e3c74754 100644 --- a/src/coreclr/vm/exinfo.cpp +++ b/src/coreclr/vm/exinfo.cpp @@ -181,9 +181,9 @@ void ExInfo::MakeCallbacksRelatedToHandler( m_EHClauseInfo.SetEHClauseType(COR_PRF_CLAUSE_FILTER); // Suppress the debugger filter notification for runtime helper that invokes - // the main program entrypoint. This method has filter clauses that may - // return false, but the debugger intercepts at the notification before the filter - // evaluates, preventing the exception from propagating as unhandled. + // the main program entrypoint (Environment.CallEntryPoint). This method has + // filter clause that may return false, but the debugger intercepts at the notification + // before the filter evaluates, preventing the exception from propagating as unhandled. if (pMD != g_pEnvironmentCallEntryPointMethodDesc) { EEToDebuggerExceptionInterfaceWrapper::ExceptionFilter(pMD, (TADDR) dwHandlerStartPC, pEHClause->FilterOffset, (BYTE*)sf.SP); From 2458690919cd9042c311694bc68772e3945a302f Mon Sep 17 00:00:00 2001 From: Jan Kotas Date: Fri, 17 Apr 2026 18:24:59 -0700 Subject: [PATCH 4/4] Update src/coreclr/vm/exinfo.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/coreclr/vm/exinfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/vm/exinfo.cpp b/src/coreclr/vm/exinfo.cpp index 6733c9e3c74754..da05037a9f4531 100644 --- a/src/coreclr/vm/exinfo.cpp +++ b/src/coreclr/vm/exinfo.cpp @@ -180,9 +180,9 @@ void ExInfo::MakeCallbacksRelatedToHandler( { m_EHClauseInfo.SetEHClauseType(COR_PRF_CLAUSE_FILTER); - // Suppress the debugger filter notification for runtime helper that invokes + // Suppress the debugger filter notification for the runtime helper that invokes // the main program entrypoint (Environment.CallEntryPoint). This method has - // filter clause that may return false, but the debugger intercepts at the notification + // a filter clause that may return false, but the debugger intercepts at the notification // before the filter evaluates, preventing the exception from propagating as unhandled. if (pMD != g_pEnvironmentCallEntryPointMethodDesc) {