Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 2 additions & 9 deletions NuGet.config
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,8 @@
<!--Begin: Package sources managed by Dependency Flow automation. Do not edit the sources below.-->
<!-- Begin: Package sources from dotnet-emsdk -->
<add key="darc-pub-dotnet-emsdk-6fd14a4" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-6fd14a46/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-2b0cca8" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2b0cca8a/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-2b0cca8-3" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2b0cca8a-3/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-2b0cca8-2" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2b0cca8a-2/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-2b0cca8-1" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-2b0cca8a-1/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-976b101" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-976b101e/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-976b101-4" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-976b101e-4/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-976b101-3" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-976b101e-3/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-976b101-2" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-976b101e-2/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-976b101-1" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-976b101e-1/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-6fd14a4-2" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-6fd14a46-2/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-6fd14a4-1" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-6fd14a46-1/nuget/v3/index.json" />
<!-- End: Package sources from dotnet-emsdk -->
<!-- Begin: Package sources from dotnet-sdk -->
<!-- End: Package sources from dotnet-sdk -->
Expand Down
4 changes: 2 additions & 2 deletions eng/Version.Details.xml
Original file line number Diff line number Diff line change
Expand Up @@ -354,9 +354,9 @@
<Uri>https://dev.azure.com/dnceng/internal/_git/dotnet-optimization</Uri>
<Sha>67613417f5e1af250e6ddfba79f8f2885d8e90fb</Sha>
</Dependency>
<Dependency Name="Microsoft.DotNet.HotReload.Utils.Generator.BuildTool" Version="8.0.0-alpha.0.25330.2">
<Dependency Name="Microsoft.DotNet.HotReload.Utils.Generator.BuildTool" Version="8.0.0-alpha.0.25378.2">
<Uri>https://github.com/dotnet/hotreload-utils</Uri>
<Sha>733b3be8cce2b6eb42a151bf95fbb05500fa40ee</Sha>
<Sha>0dcc0d22fc7b9c4eb8c7ae571ae4213324b006a6</Sha>
</Dependency>
<Dependency Name="System.Runtime.Numerics.TestData" Version="8.0.0-beta.25311.1">
<Uri>https://github.com/dotnet/runtime-assets</Uri>
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@
<MicrosoftDotNetXHarnessTestRunnersCommonVersion>8.0.0-prerelease.25270.1</MicrosoftDotNetXHarnessTestRunnersCommonVersion>
<MicrosoftDotNetXHarnessTestRunnersXunitVersion>8.0.0-prerelease.25270.1</MicrosoftDotNetXHarnessTestRunnersXunitVersion>
<MicrosoftDotNetXHarnessCLIVersion>8.0.0-prerelease.25270.1</MicrosoftDotNetXHarnessCLIVersion>
<MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>8.0.0-alpha.0.25330.2</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
<MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>8.0.0-alpha.0.25378.2</MicrosoftDotNetHotReloadUtilsGeneratorBuildToolVersion>
<XUnitVersion>2.4.2</XUnitVersion>
<XUnitAnalyzersVersion>1.0.0</XUnitAnalyzersVersion>
<XUnitRunnerVisualStudioVersion>2.4.5</XUnitRunnerVisualStudioVersion>
Expand Down
11 changes: 7 additions & 4 deletions src/coreclr/gc/gc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
266 changes: 252 additions & 14 deletions src/coreclr/pal/src/thread/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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__
Expand Down Expand Up @@ -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);
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

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

The offset variable is declared at function scope but used within a local block scope. This could lead to incorrect behavior as offset is initialized to 0 at the top of the function but then reused for a different purpose in the read operation later.

Copilot uses AI. Check for mistakes.

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)
Copy link
Preview

Copilot AI Aug 15, 2025

Choose a reason for hiding this comment

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

The variable offset is being reused for both write and read operations. Consider using separate variables (e.g., writeOffset and readOffset) to improve code clarity and prevent potential bugs.

Suggested change
if (offset == bytesToRead && event == (unsigned char)RuntimeEvent_Continue)
int readOffset = 0;
do
{
bytesRead = read(continuePipeFd, buffer + readOffset, bytesToRead - readOffset);
if (bytesRead > 0)
{
readOffset += bytesRead;
}
}
while ((bytesRead > 0 && readOffset < bytesToRead) || (bytesRead == -1 && errno == EINTR));
if (readOffset == bytesToRead && event == (unsigned char)RuntimeEvent_Continue)

Copilot uses AI. Check for mistakes.

{
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];
Expand All @@ -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;
}

Expand All @@ -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));
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading
Loading