From 0ea8b5e7523e26f394e7246c61f8b075cd7b893c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 15 Jul 2025 14:17:49 -0700 Subject: [PATCH 1/5] [release/8.0-staging] [Test Only] Disable the UTFStringConversionFailures test on CI runs (#117489) Co-authored-by: Jeremy Koritzinsky Co-authored-by: Jeremy Koritzinsky --- .../LibraryImportGenerator.Tests/CollectionMarshallingFails.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs index 9336f8caf8fe0e..eab34000e45490 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.Tests/CollectionMarshallingFails.cs @@ -107,7 +107,8 @@ public static partial void NegateBoolsRef2D_ClearMarshalling( public class CollectionMarshallingFails { [Fact] - public void UTFStringConversionFailures() + [SkipOnCI("Allocates enough memory that the OOM killer can kill the process on our Helix machines.")] + public void BigUTFStringConversionFailures() { bool threw = false; try From c11dbaf7fd1ea5323855a39fab1a3a72b75e8186 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 11:34:47 -0400 Subject: [PATCH 2/5] [release/8.0-staging] [Test Only] Fix BuildChainCustomTrustStore test --- .../tests/X509Certificates/ChainTests.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs index 92cc1abb1b6292..200f6fdbf30916 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs @@ -344,6 +344,8 @@ public static void BuildChainCustomTrustStore( chainTest.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; chainTest.ChainPolicy.ExtraStore.Add(issuerCert); + X509ChainStatusFlags allowedFlags = X509ChainStatusFlags.NoError; + switch (testArguments) { case BuildChainCustomTrustStoreTestArguments.TrustedIntermediateUntrustedRoot: @@ -361,6 +363,9 @@ public static void BuildChainCustomTrustStore( chainHolder.DisposeChainElements(); chainTest.ChainPolicy.CustomTrustStore.Remove(rootCert); chainTest.ChainPolicy.TrustMode = X509ChainTrustMode.System; + chainTest.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; + chainTest.ChainPolicy.ExtraStore.Add(rootCert); + allowedFlags |= X509ChainStatusFlags.UntrustedRoot; break; default: throw new InvalidDataException(); @@ -368,7 +373,11 @@ public static void BuildChainCustomTrustStore( Assert.Equal(chainBuildsSuccessfully, chainTest.Build(endCert)); Assert.Equal(3, chainTest.ChainElements.Count); - Assert.Equal(chainFlags, chainTest.AllStatusFlags()); + + X509ChainStatusFlags actualFlags = chainTest.AllStatusFlags(); + actualFlags &= ~allowedFlags; + + Assert.Equal(chainFlags, actualFlags); } } From 435981fbcebdda193c76ac96715625885f9f3ac8 Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 28 Jul 2025 15:31:47 -0700 Subject: [PATCH 3/5] Update dependencies from https://github.com/dotnet/hotreload-utils build 20250728.2 (#118128) Microsoft.DotNet.HotReload.Utils.Generator.BuildTool From Version 8.0.0-alpha.0.25330.2 -> To Version 8.0.0-alpha.0.25378.2 Co-authored-by: dotnet-maestro[bot] --- NuGet.config | 11 ++--------- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/NuGet.config b/NuGet.config index 5a09f7eff9d983..02506c2fe5754d 100644 --- a/NuGet.config +++ b/NuGet.config @@ -10,15 +10,8 @@ - - - - - - - - - + + diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 419ff2f1f7f411..c769a1f4836efc 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -354,9 +354,9 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-optimization 67613417f5e1af250e6ddfba79f8f2885d8e90fb - + https://github.com/dotnet/hotreload-utils - 733b3be8cce2b6eb42a151bf95fbb05500fa40ee + 0dcc0d22fc7b9c4eb8c7ae571ae4213324b006a6 https://github.com/dotnet/runtime-assets diff --git a/eng/Versions.props b/eng/Versions.props index 01d2fa496566c5..1c1e1719bbf3f6 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -198,7 +198,7 @@ 8.0.0-prerelease.25270.1 8.0.0-prerelease.25270.1 8.0.0-prerelease.25270.1 - 8.0.0-alpha.0.25330.2 + 8.0.0-alpha.0.25378.2 2.4.2 1.0.0 2.4.5 From 28a27a43fc62d0f4514075646aa9f20827741daf Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 15:02:56 -0700 Subject: [PATCH 4/5] fixing a bug in card mark stealing (#118009) Backport of #117968 to release/8.0-staging --- src/coreclr/gc/gc.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index c0086bed2f10f0..74143fc8df86de 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -41060,10 +41060,13 @@ BOOL gc_heap::card_transition (uint8_t* po, uint8_t* end, size_t card_word_end, //dprintf(3,(" Clearing cards [%zx, %zx[ ", dprintf(3,(" CC [%zx, %zx[ ", (size_t)card_address(card), (size_t)po)); - clear_cards (card, card_of(po)); - n_card_set -= (card_of (po) - card); - n_cards_cleared += (card_of (po) - card); - + uint8_t* card_clearing_limit = po; +#ifdef FEATURE_CARD_MARKING_STEALING + card_clearing_limit = min (limit, po); +#endif // FEATURE_CARD_MARKING_STEALING + clear_cards (card, card_of (card_clearing_limit)); + n_card_set -= (card_of (card_clearing_limit) - card); + n_cards_cleared += (card_of (card_clearing_limit) - card); } n_eph +=cg_pointers_found; cg_pointers_found = 0; From 4e270e8247a28420d76b48ff1293910a63010f20 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 5 Aug 2025 13:52:20 -0400 Subject: [PATCH 5/5] [release/8.0-staging] Fix broken debugger/debuggee startup handshake protocol on macOS26. (#118213) Backport of https://github.com/dotnet/runtime/pull/118120 * Add support for new startup handshake protocol over pipes instead of sempahores. * Remove NonBlocking runtime support. * Renames, logging and simplification. * Improve tracing. * Make open check non blocking. * Fold access into open calls and track ENOENT | ENOACCES * Review feedback. --------- Co-authored-by: lateralusX --- src/coreclr/pal/src/thread/process.cpp | 266 +++++++++++++++++++++++-- 1 file changed, 252 insertions(+), 14 deletions(-) diff --git a/src/coreclr/pal/src/thread/process.cpp b/src/coreclr/pal/src/thread/process.cpp index f9f2703cf4b23d..582f6cedc2dc7c 100644 --- a/src/coreclr/pal/src/thread/process.cpp +++ b/src/coreclr/pal/src/thread/process.cpp @@ -103,6 +103,9 @@ extern "C" } \ } while (false) +// On macOS 26, sem_open fails if debugger and debugee are signed with different team ids. +// Use fifos instead of semaphores to avoid this issue, https://github.com/dotnet/runtime/issues/116545 +#define ENABLE_RUNTIME_EVENTS_OVER_PIPES #endif // __APPLE__ #ifdef __NetBSD__ @@ -1430,21 +1433,217 @@ static uint64_t HashSemaphoreName(uint64_t a, uint64_t b) static const char *const TwoWayNamedPipePrefix = "clr-debug-pipe"; static const char* IpcNameFormat = "%s-%d-%llu-%s"; -/*++ - PAL_NotifyRuntimeStarted +#ifdef ENABLE_RUNTIME_EVENTS_OVER_PIPES +static const char* RuntimeStartupPipeName = "st"; +static const char* RuntimeContinuePipeName = "co"; - Signals the debugger waiting for runtime startup notification to continue and - waits until the debugger signals us to continue. +#define PIPE_OPEN_RETRY_DELAY_NS 500000000 // 500 ms -Parameters: - None +typedef enum +{ + RuntimeEventsOverPipes_Disabled = 0, + RuntimeEventsOverPipes_Succeeded = 1, + RuntimeEventsOverPipes_Failed = 2, +} RuntimeEventsOverPipes; -Return value: - TRUE - successfully launched by debugger, FALSE - not launched or some failure in the handshake ---*/ +typedef enum +{ + RuntimeEvent_Unknown = 0, + RuntimeEvent_Started = 1, + RuntimeEvent_Continue = 2, +} RuntimeEvent; + +static +int +OpenPipe(const char* name, int mode) +{ + int fd = -1; + int flags = mode | O_NONBLOCK; + +#if defined(FD_CLOEXEC) + flags |= O_CLOEXEC; +#endif + + while (fd == -1) + { + fd = open(name, flags); + if (fd == -1) + { + if (mode == O_WRONLY && errno == ENXIO) + { + PAL_nanosleep(PIPE_OPEN_RETRY_DELAY_NS); + continue; + } + else if (errno == EINTR) + { + continue; + } + else + { + break; + } + } + } + + if (fd != -1) + { + flags = fcntl(fd, F_GETFL); + if (flags != -1) + { + flags &= ~O_NONBLOCK; + if (fcntl(fd, F_SETFL, flags) == -1) + { + close(fd); + fd = -1; + } + } + else + { + close(fd); + fd = -1; + } + } + + return fd; +} + +static +void +ClosePipe(int fd) +{ + if (fd != -1) + { + while (close(fd) < 0 && errno == EINTR); + } +} + +static +RuntimeEventsOverPipes +NotifyRuntimeUsingPipes() +{ + RuntimeEventsOverPipes result = RuntimeEventsOverPipes_Disabled; + char startupPipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH]; + char continuePipeName[MAX_DEBUGGER_TRANSPORT_PIPE_NAME_LENGTH]; + int startupPipeFd = -1; + int continuePipeFd = -1; + size_t offset = 0; + + LPCSTR applicationGroupId = PAL_GetApplicationGroupId(); + + PAL_GetTransportPipeName(continuePipeName, gPID, applicationGroupId, RuntimeContinuePipeName); + TRACE("NotifyRuntimeUsingPipes: opening continue '%s' pipe\n", continuePipeName); + + continuePipeFd = OpenPipe(continuePipeName, O_RDONLY); + if (continuePipeFd == -1) + { + if (errno == ENOENT || errno == EACCES) + { + TRACE("NotifyRuntimeUsingPipes: pipe %s not found/accessible, runtime events over pipes disabled\n", continuePipeName); + } + else + { + TRACE("NotifyRuntimeUsingPipes: open(%s) failed: %d (%s)\n", continuePipeName, errno, strerror(errno)); + result = RuntimeEventsOverPipes_Failed; + } + + goto exit; + } + + PAL_GetTransportPipeName(startupPipeName, gPID, applicationGroupId, RuntimeStartupPipeName); + TRACE("NotifyRuntimeUsingPipes: opening startup '%s' pipe\n", startupPipeName); + + startupPipeFd = OpenPipe(startupPipeName, O_WRONLY); + if (startupPipeFd == -1) + { + if (errno == ENOENT || errno == EACCES) + { + TRACE("NotifyRuntimeUsingPipes: pipe %s not found/accessible, runtime events over pipes disabled\n", startupPipeName); + } + else + { + TRACE("NotifyRuntimeUsingPipes: open(%s) failed: %d (%s)\n", startupPipeName, errno, strerror(errno)); + result = RuntimeEventsOverPipes_Failed; + } + + goto exit; + } + + TRACE("NotifyRuntimeUsingPipes: sending started event\n"); + + { + unsigned char event = (unsigned char)RuntimeEvent_Started; + unsigned char *buffer = &event; + int bytesToWrite = sizeof(event); + int bytesWritten = 0; + + do + { + bytesWritten = write(startupPipeFd, buffer + offset, bytesToWrite - offset); + if (bytesWritten > 0) + { + offset += bytesWritten; + } + } + while ((bytesWritten > 0 && offset < bytesToWrite) || (bytesWritten == -1 && errno == EINTR)); + + if (offset != bytesToWrite) + { + TRACE("NotifyRuntimeUsingPipes: write(%s) failed: %d (%s)\n", startupPipeName, errno, strerror(errno)); + goto exit; + } + } + + TRACE("NotifyRuntimeUsingPipes: waiting on continue event\n"); + + { + unsigned char event = (unsigned char)RuntimeEvent_Unknown; + unsigned char *buffer = &event; + int bytesToRead = sizeof(event); + int bytesRead = 0; + + offset = 0; + do + { + bytesRead = read(continuePipeFd, buffer + offset, bytesToRead - offset); + if (bytesRead > 0) + { + offset += bytesRead; + } + } + while ((bytesRead > 0 && offset < bytesToRead) || (bytesRead == -1 && errno == EINTR)); + + if (offset == bytesToRead && event == (unsigned char)RuntimeEvent_Continue) + { + TRACE("NotifyRuntimeUsingPipes: received continue event\n"); + } + else + { + TRACE("NotifyRuntimeUsingPipes: received invalid event\n"); + goto exit; + } + } + + result = RuntimeEventsOverPipes_Succeeded; + +exit: + + if (startupPipeFd != -1) + { + ClosePipe(startupPipeFd); + } + + if (continuePipeFd != -1) + { + ClosePipe(continuePipeFd); + } + + return result; +} +#endif // ENABLE_RUNTIME_EVENTS_OVER_PIPES + +static BOOL -PALAPI -PAL_NotifyRuntimeStarted() +NotifyRuntimeUsingSemaphores() { char startupSemName[CLR_SEM_MAX_NAMELEN]; char continueSemName[CLR_SEM_MAX_NAMELEN]; @@ -1465,13 +1664,13 @@ PAL_NotifyRuntimeStarted() CreateSemaphoreName(startupSemName, RuntimeStartupSemaphoreName, unambiguousProcessDescriptor, applicationGroupId); CreateSemaphoreName(continueSemName, RuntimeContinueSemaphoreName, unambiguousProcessDescriptor, applicationGroupId); - TRACE("PAL_NotifyRuntimeStarted opening continue '%s' startup '%s'\n", continueSemName, startupSemName); + TRACE("NotifyRuntimeUsingSemaphores: opening continue '%s' startup '%s'\n", continueSemName, startupSemName); // Open the debugger startup semaphore. If it doesn't exists, then we do nothing and return startupSem = sem_open(startupSemName, 0); if (startupSem == SEM_FAILED) { - TRACE("sem_open(%s) failed: %d (%s)\n", startupSemName, errno, strerror(errno)); + TRACE("NotifyRuntimeUsingSemaphores: sem_open(%s) failed: %d (%s)\n", startupSemName, errno, strerror(errno)); goto exit; } @@ -1494,7 +1693,7 @@ PAL_NotifyRuntimeStarted() { if (EINTR == errno) { - TRACE("sem_wait() failed with EINTR; re-waiting"); + TRACE("NotifyRuntimeUsingSemaphores: sem_wait() failed with EINTR; re-waiting"); continue; } ASSERT("sem_wait(continueSem) failed: errno is %d (%s)\n", errno, strerror(errno)); @@ -1516,6 +1715,45 @@ PAL_NotifyRuntimeStarted() return launched; } +/*++ + PAL_NotifyRuntimeStarted + + Signals the debugger waiting for runtime startup notification to continue and + waits until the debugger signals us to continue. + +Parameters: + None + +Return value: + TRUE - successfully launched by debugger, FALSE - not launched or some failure in the handshake +--*/ +BOOL +PALAPI +PAL_NotifyRuntimeStarted() +{ +#ifdef ENABLE_RUNTIME_EVENTS_OVER_PIPES + // Test pipes as runtime event transport. + RuntimeEventsOverPipes result = NotifyRuntimeUsingPipes(); + switch (result) + { + case RuntimeEventsOverPipes_Disabled: + TRACE("PAL_NotifyRuntimeStarted: pipe handshake disabled, try semaphores\n"); + return NotifyRuntimeUsingSemaphores(); + case RuntimeEventsOverPipes_Failed: + TRACE("PAL_NotifyRuntimeStarted: pipe handshake failed\n"); + return FALSE; + case RuntimeEventsOverPipes_Succeeded: + TRACE("PAL_NotifyRuntimeStarted: pipe handshake succeeded\n"); + return TRUE; + default: + // Unexpected result. + return FALSE; + } +#else + return NotifyRuntimeUsingSemaphores(); +#endif // ENABLE_RUNTIME_EVENTS_OVER_PIPES +} + LPCSTR PALAPI PAL_GetApplicationGroupId()